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 "scsi_ddk_service.h"
17
18 #include <hdf_base.h>
19 #include <cerrno>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cstring>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25 #include <securec.h>
26 #include <sys/ioctl.h>
27 #include <scsi/sg.h>
28 #include <unistd.h>
29
30 #include "ddk_sysfs_dev_node.h"
31 #include "hdf_log.h"
32 #include "usbd_wrapper.h"
33 #include "usb_ddk_permission.h"
34
35 #ifdef __LITEOS__
36 #include "scsi_liteos_adapter.h"
37 #else
38 #include "scsi_linux_adapter.h"
39 #endif
40
41 #define HDF_LOG_TAG scsi_ddk_service
42 using namespace OHOS::HDI::Usb::Ddk;
43
44 namespace OHOS {
45 namespace HDI {
46 namespace Usb {
47 namespace ScsiDdk {
48 namespace V1_0 {
49
50 constexpr uint8_t THIRTY_TWO_BIT = 32;
51 constexpr uint8_t SCSIPERIPHERAL_MAX_SENSE_DATA_LEN = 252;
52 constexpr uint8_t SCSIPERIPHERAL_VENDOR_ID_LEN = 8;
53 constexpr uint8_t SCSIPERIPHERAL_PRODUCT_ID_LEN = 16;
54 constexpr uint8_t SCSIPERIPHERAL_PRODUCT_REV_LEN = 4;
55 constexpr uint8_t PATH_LEN = 50;
56 constexpr uint8_t ONE_BYTE = 1;
57 constexpr uint8_t TWO_BYTE = 2;
58 constexpr uint8_t THREE_BYTE = 3;
59 constexpr uint8_t FOUR_BYTE = 4;
60 constexpr uint8_t FIVE_BYTE = 5;
61 constexpr uint8_t SIX_BYTE = 6;
62 constexpr uint8_t SEVEN_BYTE = 7;
63 constexpr uint8_t EIGHT_BYTE = 8;
64 constexpr uint8_t NINE_BYTE = 9;
65 constexpr uint8_t SIXTEEN_BYTE = 16;
66 constexpr uint8_t THIRTY_TWO_BYTE = 32;
67 constexpr uint8_t EIGHT_BIT = 8;
68 constexpr uint8_t SIXTEEN_BIT = 16;
69 constexpr uint8_t TWENTY_FOUR_BIT = 24;
70 constexpr uint8_t BYTE_MASK = 0xFF;
71 constexpr uint32_t TIMEOUT = 5000;
72 constexpr uint8_t OPERATION_CODE_READCAPACITY10 = 0x25;
73 constexpr uint8_t OPERATION_CODE_TESTUNITREADY = 0x00;
74 constexpr uint8_t OPERATION_CODE_INQUIRY = 0x12;
75 constexpr uint8_t OPERATION_CODE_REQUEST_SENSE = 0x03;
76 constexpr uint8_t OPERATION_CODE_READ10 = 0x28;
77 constexpr uint8_t OPERATION_CODE_WRITE10 = 0x2A;
78 constexpr uint8_t OPERATION_CODE_VERIFY10 = 0x2F;
79 constexpr uint8_t CDB_LENGTH_SIX = 6;
80 constexpr uint8_t CDB_LENGTH_TEN = 10;
81 constexpr uint32_t MAX_TRANSFER_BYTES = UINT32_MAX;
82 constexpr uint32_t MAX_MEM_MAP_SIZE = UINT32_MAX;
83 constexpr const char* SCSIPERIPHERAL_DEVICE_MMAP_PATH = "/data/service/el1/public/usb/scsi";
84 static const std::string PERMISSION_NAME = "ohos.permission.ACCESS_DDK_SCSI_PERIPHERAL";
85 std::mutex g_memMapMutex;
86
87 class MemMapFinalizer {
88 public:
MemMapFinalizer(uint8_t * buffer,uint32_t size)89 MemMapFinalizer(uint8_t *buffer, uint32_t size)
90 : buffer_(buffer), size_(size)
91 {
92 }
93
~MemMapFinalizer()94 ~MemMapFinalizer()
95 {
96 munmap(buffer_, size_);
97 }
98
99 private:
100 MemMapFinalizer(const MemMapFinalizer&);
101 void operator=(const MemMapFinalizer&);
102
103 private:
104 uint8_t *buffer_ = nullptr;
105 uint32_t size_ = 0;
106 };
107
108 template<typename Func, typename ResultType = decltype(std::declval<Func>()())>
TrackTime(Func && func,const char * desc="")109 ResultType TrackTime(Func&& func, const char* desc = "")
110 {
111 auto start = std::chrono::high_resolution_clock::now();
112 ResultType result = func();
113 auto end = std::chrono::high_resolution_clock::now();
114 auto duration_ms = std::chrono::duration<double, std::milli>(end - start);
115 HDF_LOGD("Function [%{public}s] took [%{public}.2f]ms with result [%{public}d]", desc, duration_ms.count(), result);
116 return result;
117 }
118
GetBusNum(uint64_t devHandle)119 inline uint32_t GetBusNum(uint64_t devHandle)
120 {
121 return static_cast<uint32_t>(devHandle >> THIRTY_TWO_BIT);
122 }
123
GetDevNum(uint64_t devHandle)124 inline uint32_t GetDevNum(uint64_t devHandle)
125 {
126 return static_cast<uint32_t>(devHandle & 0xFFFFFFFF);
127 }
128
VerifyPermission(const std::string & permissionName)129 static bool VerifyPermission(const std::string &permissionName)
130 {
131 return DdkPermissionManager::VerifyPermission(permissionName);
132 }
133
SetUint16(unsigned char * cdb,int start,uint16_t val)134 static inline void SetUint16(unsigned char *cdb, int start, uint16_t val)
135 {
136 cdb[start] = (val >> EIGHT_BIT) & BYTE_MASK;
137 cdb[start + ONE_BYTE] = val & BYTE_MASK;
138 }
139
SetUint32(unsigned char * cdb,int start,uint32_t val)140 static inline void SetUint32(unsigned char *cdb, int start, uint32_t val)
141 {
142 cdb[start] = (val >> TWENTY_FOUR_BIT) & BYTE_MASK;
143 cdb[start + ONE_BYTE] = (val >> SIXTEEN_BIT) & BYTE_MASK;
144 cdb[start + TWO_BYTE] = (val >> EIGHT_BIT) & BYTE_MASK;
145 cdb[start + THREE_BYTE] = val & BYTE_MASK;
146 }
147
GetUint32(unsigned char * buf,int start)148 static inline uint32_t GetUint32(unsigned char *buf, int start)
149 {
150 return (
151 (static_cast<uint32_t>(buf[start]) << TWENTY_FOUR_BIT) |
152 (static_cast<uint32_t>(buf[start + ONE_BYTE]) << SIXTEEN_BIT) |
153 (static_cast<uint32_t>(buf[start + TWO_BYTE]) << EIGHT_BIT) |
154 (static_cast<uint32_t>(buf[start + THREE_BYTE]))
155 );
156 }
157
BuildCdbForReadAndWrite(const ScsiPeripheralIORequest & request,unsigned char cdb[CDB_LENGTH_TEN],uint8_t operationCode)158 static void BuildCdbForReadAndWrite(const ScsiPeripheralIORequest& request, unsigned char cdb[CDB_LENGTH_TEN],
159 uint8_t operationCode)
160 {
161 cdb[0] = operationCode;
162 cdb[ONE_BYTE] = request.byte1;
163 SetUint32(cdb, TWO_BYTE, request.lbAddress);
164 cdb[SIX_BYTE] = request.byte6;
165 SetUint16(cdb, SEVEN_BYTE, request.transferLength);
166 cdb[NINE_BYTE] = request.control;
167 }
168
AllocateAndInitializeBuffer(const ScsiPeripheralDevice & dev,uint32_t memMapSize,uint8_t * & buffer,uint16_t allocationLength)169 static int32_t AllocateAndInitializeBuffer(const ScsiPeripheralDevice& dev, uint32_t memMapSize, uint8_t*& buffer,
170 uint16_t allocationLength)
171 {
172 if (memMapSize < allocationLength || memMapSize > MAX_MEM_MAP_SIZE) {
173 HDF_LOGE("%{public}s: memMapSize is invalid. memMapSize=%{public}d, allocationLength=%{public}d", __func__,
174 memMapSize, allocationLength);
175 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
176 }
177 buffer = static_cast<uint8_t *>(mmap(nullptr, memMapSize, PROT_READ | PROT_WRITE, MAP_SHARED, dev.memMapFd, 0));
178 if (buffer == MAP_FAILED) {
179 HDF_LOGE("%{public}s: mmap failed, errno=%{public}d, memMapFd=%{public}d, memMapSize=%{public}d", __func__,
180 errno, dev.memMapFd, memMapSize);
181 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
182 }
183
184 int32_t ret = memset_s(buffer, memMapSize, 0, memMapSize);
185 if (ret != 0) {
186 HDF_LOGE("%{public}s memset_s(io_hdr) failed, ret=%{public}d", __func__, ret);
187 munmap(buffer, memMapSize);
188 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
189 }
190 return HDF_SUCCESS;
191 }
192
UpdateResponseFromOsAdapter(ScsiPeripheralResponse & response,const Response & resp)193 static void UpdateResponseFromOsAdapter(ScsiPeripheralResponse& response, const Response& resp)
194 {
195 response.senseData.assign(resp.senseData.begin(), resp.senseData.end());
196 response.status = resp.status;
197 response.maskedStatus = resp.maskedStatus;
198 response.msgStatus = resp.msgStatus;
199 response.sbLenWr = resp.sbLenWr;
200 response.hostStatus = resp.hostStatus;
201 response.driverStatus = resp.driverStatus;
202 response.resId = resp.resId;
203 response.duration = resp.duration;
204 response.transferredLength = resp.transferredLength;
205 }
206
ScsiPeripheralDdkImplGetInstance(void)207 extern "C" IScsiPeripheralDdk *ScsiPeripheralDdkImplGetInstance(void)
208 {
209 std::shared_ptr<ScsiOsAdapter> osAdapter;
210 #ifdef __LITEOS__
211 osAdapter = std::make_shared<LiteosScsiOsAdapter>();
212 #else
213 osAdapter = std::make_shared<LinuxScsiOsAdapter>();
214 #endif
215 return new (std::nothrow) ScsiDdkService(osAdapter);
216 }
217
Init()218 int32_t ScsiDdkService::Init()
219 {
220 HDF_LOGD("ScsiDdkService::Init start");
221 if (!VerifyPermission(PERMISSION_NAME)) {
222 HDF_LOGI("%{public}s: no permission", __func__);
223 return SCSIPERIPHERAL_DDK_NO_PERM;
224 }
225
226 return HDF_SUCCESS;
227 }
228
Release()229 int32_t ScsiDdkService::Release()
230 {
231 HDF_LOGD("ScsiDdkService::Release start");
232 if (!VerifyPermission(PERMISSION_NAME)) {
233 HDF_LOGE("%{public}s: no permission", __func__);
234 return SCSIPERIPHERAL_DDK_NO_PERM;
235 }
236
237 DdkPermissionManager::Reset();
238
239 return HDF_SUCCESS;
240 }
241
Open(uint64_t deviceId,uint8_t interfaceIndex,ScsiPeripheralDevice & dev,int & memMapFd)242 int32_t ScsiDdkService::Open(uint64_t deviceId, uint8_t interfaceIndex, ScsiPeripheralDevice& dev, int &memMapFd)
243 {
244 HDF_LOGD("ScsiDdkService::Open start");
245 if (!VerifyPermission(PERMISSION_NAME)) {
246 HDF_LOGI("%{public}s: no permission", __func__);
247 return SCSIPERIPHERAL_DDK_NO_PERM;
248 }
249
250 uint16_t busNum = GetBusNum(deviceId);
251 uint16_t devNum = GetDevNum(deviceId);
252 SysfsDevNode devNode(busNum, devNum, interfaceIndex, "sg");
253 std::string path;
254 int32_t ret = devNode.FindPath(path);
255 if (ret != HDF_SUCCESS) {
256 HDF_LOGE("Get devNodePath ret: %{public}d\n", ret);
257 return SCSIPERIPHERAL_DDK_DEVICE_NOT_FOUND;
258 }
259
260 int32_t fd = TrackTime([&]() {
261 return open(path.c_str(), O_RDWR);
262 }, __func__);
263 if (fd < 0) {
264 HDF_LOGE("%{public}s open failed, path=%{public}s, errno=%{public}d", __func__, path.c_str(), errno);
265 return SCSIPERIPHERAL_DDK_IO_ERROR;
266 }
267
268 dev.devFd = fd;
269 HDF_LOGD("Open success, dev.devFd=%{public}d, path.c_str()=%{public}s", dev.devFd, path.c_str());
270
271 ret = GetDeviceMemMapFd(busNum, devNum, interfaceIndex, memMapFd);
272 if (ret != HDF_SUCCESS) {
273 HDF_LOGE("GetDeviceMemMapFd failed, ret=%{public}d", ret);
274 return ret;
275 }
276 dev.memMapFd = memMapFd;
277
278 ScsiPeripheralReadCapacityRequest request;
279 ScsiPeripheralCapacityInfo capacityInfo;
280 ScsiPeripheralResponse response;
281 request.lbAddress = 0;
282 request.byte8 = 0;
283 request.control = 0;
284 request.timeout = TIMEOUT;
285
286 ret = ReadCapacity10(dev, request, capacityInfo, response);
287 if (ret != HDF_SUCCESS) {
288 HDF_LOGE("ReadCapacity10 failed, ret=%{public}d", ret);
289 return ret;
290 }
291
292 dev.lbLength = capacityInfo.lbLength;
293 HDF_LOGD("ReadCapacity success, dev.lbLength=%{public}d", dev.lbLength);
294
295 return HDF_SUCCESS;
296 }
297
Close(const ScsiPeripheralDevice & dev)298 int32_t ScsiDdkService::Close(const ScsiPeripheralDevice& dev)
299 {
300 HDF_LOGD("ScsiDdkService::Close start");
301 if (!VerifyPermission(PERMISSION_NAME)) {
302 HDF_LOGE("%{public}s: no permission", __func__);
303 return SCSIPERIPHERAL_DDK_NO_PERM;
304 }
305
306 int32_t ret = TrackTime([&]() {
307 return close(dev.devFd);
308 }, __func__);
309 if (ret == -1) {
310 HDF_LOGE("%{public}s close failed", __func__);
311 return SCSIPERIPHERAL_DDK_IO_ERROR;
312 }
313
314 ret = TrackTime([&]() {
315 return close(dev.memMapFd);
316 }, __func__);
317 if (ret < 0) {
318 HDF_LOGE("%{public}s: close failed, memMapFd=%{public}d, errno=%{public}d", __func__, dev.memMapFd, errno);
319 return SCSIPERIPHERAL_DDK_IO_ERROR;
320 }
321
322 return HDF_SUCCESS;
323 }
324
ReadCapacity10(const ScsiPeripheralDevice & dev,const ScsiPeripheralReadCapacityRequest & request,ScsiPeripheralCapacityInfo & capacityInfo,ScsiPeripheralResponse & response)325 int32_t ScsiDdkService::ReadCapacity10(const ScsiPeripheralDevice& dev,
326 const ScsiPeripheralReadCapacityRequest& request, ScsiPeripheralCapacityInfo& capacityInfo,
327 ScsiPeripheralResponse& response)
328 {
329 HDF_LOGD("ScsiDdkService::ReadCapacity10 start");
330 if (!VerifyPermission(PERMISSION_NAME)) {
331 HDF_LOGE("%{public}s: no permission", __func__);
332 return SCSIPERIPHERAL_DDK_NO_PERM;
333 }
334
335 Request req;
336 uint8_t cdb[CDB_LENGTH_TEN];
337 cdb[0] = OPERATION_CODE_READCAPACITY10;
338 SetUint32(cdb, TWO_BYTE, request.lbAddress);
339 cdb[EIGHT_BYTE] = request.byte8;
340 cdb[NINE_BYTE] = request.control;
341 req.commandDescriptorBlock.assign(cdb, cdb + sizeof(cdb));
342 req.dataTransferDirection = SG_DXFER_FROM_DEV;
343 req.timeout = request.timeout;
344 req.devFd = dev.devFd;
345
346 if (osAdapter_ == nullptr) {
347 HDF_LOGE("%{public}s: osAdapter_ is null.", __func__);
348 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
349 }
350
351 std::vector<uint8_t> data(sizeof(capacityInfo));
352 Response resp;
353 int32_t ret = TrackTime([&]() {
354 return osAdapter_->SendRequest(req, data.data(), data.size(), resp);
355 }, __func__);
356 if (ret != HDF_SUCCESS) {
357 HDF_LOGE("%{public}s: SendRequest failed, ret=%{public}d", __func__, ret);
358 return ret;
359 }
360
361 UpdateResponseFromOsAdapter(response, resp);
362
363 capacityInfo.lbAddress = GetUint32(data.data(), 0);
364 capacityInfo.lbLength = GetUint32(data.data(), FOUR_BYTE);
365
366 return HDF_SUCCESS;
367 }
368
TestUnitReady(const ScsiPeripheralDevice & dev,const ScsiPeripheralTestUnitReadyRequest & request,ScsiPeripheralResponse & response)369 int32_t ScsiDdkService::TestUnitReady(const ScsiPeripheralDevice& dev,
370 const ScsiPeripheralTestUnitReadyRequest& request, ScsiPeripheralResponse& response)
371 {
372 HDF_LOGD("ScsiDdkService::TestUnitReady start");
373 if (!VerifyPermission(PERMISSION_NAME)) {
374 HDF_LOGE("%{public}s: no permission", __func__);
375 return SCSIPERIPHERAL_DDK_NO_PERM;
376 }
377
378 Request req;
379 unsigned char cdb[CDB_LENGTH_SIX];
380 cdb[0] = OPERATION_CODE_TESTUNITREADY;
381 SetUint32(cdb, 1, 0);
382 cdb[FIVE_BYTE] = request.control;
383 req.commandDescriptorBlock.assign(cdb, cdb + sizeof(cdb));
384 req.dataTransferDirection = SG_DXFER_NONE;
385 req.timeout = request.timeout;
386 req.devFd = dev.devFd;
387
388 if (osAdapter_ == nullptr) {
389 HDF_LOGE("%{public}s: osAdapter_ is null.", __func__);
390 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
391 }
392
393 Response resp;
394 int32_t ret = TrackTime([&]() {
395 return osAdapter_->SendRequest(req, nullptr, 0, resp);
396 }, __func__);
397 if (ret != HDF_SUCCESS) {
398 HDF_LOGE("%{public}s: SendRequest failed, ret=%{public}d", __func__, ret);
399 return ret;
400 }
401
402 UpdateResponseFromOsAdapter(response, resp);
403
404 return HDF_SUCCESS;
405 }
406
Inquiry(const ScsiPeripheralDevice & dev,const ScsiPeripheralInquiryRequest & request,ScsiPeripheralInquiryInfo & inquiryInfo,ScsiPeripheralResponse & response)407 int32_t ScsiDdkService::Inquiry(const ScsiPeripheralDevice& dev, const ScsiPeripheralInquiryRequest& request,
408 ScsiPeripheralInquiryInfo& inquiryInfo, ScsiPeripheralResponse& response)
409 {
410 HDF_LOGD("ScsiDdkService::Inquiry start");
411 if (!VerifyPermission(PERMISSION_NAME)) {
412 HDF_LOGE("%{public}s: no permission", __func__);
413 return SCSIPERIPHERAL_DDK_NO_PERM;
414 }
415
416 Request req;
417 uint8_t cdb[CDB_LENGTH_SIX];
418 cdb[0] = OPERATION_CODE_INQUIRY;
419 cdb[ONE_BYTE] = request.byte1;
420 cdb[TWO_BYTE] = request.pageCode;
421 SetUint16(cdb, THREE_BYTE, request.allocationLength);
422 cdb[FIVE_BYTE] = request.control;
423 req.commandDescriptorBlock.assign(cdb, cdb + sizeof(cdb));
424 req.dataTransferDirection = SG_DXFER_FROM_DEV;
425 req.timeout = request.timeout;
426 req.devFd = dev.devFd;
427
428 std::lock_guard<std::mutex> lock(g_memMapMutex);
429 uint8_t* buffer = nullptr;
430 uint32_t memMapSize = request.memMapSize;
431 if (memMapSize < THIRTY_TWO_BYTE + SCSIPERIPHERAL_PRODUCT_REV_LEN) {
432 HDF_LOGE("%{public}s: memMapSize should be greater than %{public}d", __func__,
433 THIRTY_TWO_BYTE + SCSIPERIPHERAL_PRODUCT_REV_LEN);
434 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
435 }
436
437 int32_t ret = AllocateAndInitializeBuffer(dev, memMapSize, buffer, request.allocationLength);
438 if (ret != HDF_SUCCESS) {
439 return ret;
440 }
441 MemMapFinalizer memMapFinalizer(buffer, memMapSize);
442
443 if (osAdapter_ == nullptr) {
444 HDF_LOGE("%{public}s: osAdapter_ is null.", __func__);
445 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
446 }
447
448 Response resp;
449 ret = TrackTime([&]() {
450 return osAdapter_->SendRequest(req, buffer, request.allocationLength, resp);
451 }, __func__);
452 if (ret != HDF_SUCCESS) {
453 HDF_LOGE("%{public}s: SendRequest failed, ret=%{public}d", __func__, ret);
454 return ret;
455 }
456
457 UpdateResponseFromOsAdapter(response, resp);
458
459 inquiryInfo.deviceType = buffer[0] & 0x1f;
460 inquiryInfo.idVendor.assign(buffer + EIGHT_BYTE, buffer + EIGHT_BYTE + SCSIPERIPHERAL_VENDOR_ID_LEN);
461 inquiryInfo.idProduct.assign(buffer + SIXTEEN_BYTE, buffer + SIXTEEN_BYTE + SCSIPERIPHERAL_PRODUCT_ID_LEN);
462 inquiryInfo.revProduct.assign(buffer + THIRTY_TWO_BYTE, buffer + THIRTY_TWO_BYTE + SCSIPERIPHERAL_PRODUCT_REV_LEN);
463
464 return HDF_SUCCESS;
465 }
466
RequestSense(const ScsiPeripheralDevice & dev,const ScsiPeripheralRequestSenseRequest & request,ScsiPeripheralResponse & response)467 int32_t ScsiDdkService::RequestSense(const ScsiPeripheralDevice& dev,
468 const ScsiPeripheralRequestSenseRequest& request, ScsiPeripheralResponse& response)
469 {
470 HDF_LOGD("ScsiDdkService::RequestSense start");
471 if (!VerifyPermission(PERMISSION_NAME)) {
472 HDF_LOGE("%{public}s: no permission", __func__);
473 return SCSIPERIPHERAL_DDK_NO_PERM;
474 }
475
476 Request req;
477 unsigned char cdb[CDB_LENGTH_SIX];
478 cdb[0] = OPERATION_CODE_REQUEST_SENSE;
479 cdb[ONE_BYTE] = request.byte1;
480 cdb[FOUR_BYTE] = request.allocationLength;
481 cdb[FIVE_BYTE] = request.control;
482 req.commandDescriptorBlock.assign(cdb, cdb + sizeof(cdb));
483 req.dataTransferDirection = SG_DXFER_FROM_DEV;
484 req.timeout = request.timeout;
485 req.devFd = dev.devFd;
486
487 if (osAdapter_ == nullptr) {
488 HDF_LOGE("%{public}s: osAdapter_ is null.", __func__);
489 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
490 }
491
492 uint32_t bufferSize = request.allocationLength < SCSIPERIPHERAL_MAX_SENSE_DATA_LEN ? request.allocationLength :
493 SCSIPERIPHERAL_MAX_SENSE_DATA_LEN;
494 Response resp;
495 resp.senseData.resize(bufferSize);
496 int32_t ret = TrackTime([&]() {
497 return osAdapter_->SendRequest(req, resp.senseData.data(), bufferSize, resp);
498 }, __func__);
499 if (ret != HDF_SUCCESS) {
500 HDF_LOGE("%{public}s: SendRequest failed, ret=%{public}d", __func__, ret);
501 return ret;
502 }
503
504 response.senseData.resize(SCSIPERIPHERAL_MAX_SENSE_DATA_LEN);
505 UpdateResponseFromOsAdapter(response, resp);
506
507 return HDF_SUCCESS;
508 }
509
Read10(const ScsiPeripheralDevice & dev,const ScsiPeripheralIORequest & request,ScsiPeripheralResponse & response)510 int32_t ScsiDdkService::Read10(const ScsiPeripheralDevice& dev,
511 const ScsiPeripheralIORequest& request, ScsiPeripheralResponse& response)
512 {
513 HDF_LOGD("ScsiDdkService::Read10 start");
514 if (!VerifyPermission(PERMISSION_NAME)) {
515 HDF_LOGE("%{public}s: no permission", __func__);
516 return SCSIPERIPHERAL_DDK_NO_PERM;
517 }
518
519 if (request.transferLength * dev.lbLength * (uint64_t)1 > MAX_TRANSFER_BYTES) {
520 HDF_LOGE("%{public}s: The value of transferLength is too large", __func__);
521 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
522 }
523
524 Request req;
525 unsigned char cdb[CDB_LENGTH_TEN];
526 BuildCdbForReadAndWrite(request, cdb, OPERATION_CODE_READ10);
527 req.commandDescriptorBlock.assign(cdb, cdb + sizeof(cdb));
528 req.dataTransferDirection = SG_DXFER_FROM_DEV;
529 req.timeout = request.timeout;
530 req.devFd = dev.devFd;
531
532 std::lock_guard<std::mutex> lock(g_memMapMutex);
533 uint8_t* buffer = nullptr;
534 uint32_t memMapSize = request.memMapSize;
535 uint32_t bufferSize = request.transferLength * dev.lbLength;
536 int32_t ret = AllocateAndInitializeBuffer(dev, memMapSize, buffer, bufferSize);
537 if (ret != HDF_SUCCESS) {
538 return ret;
539 }
540 MemMapFinalizer memMapFinalizer(buffer, memMapSize);
541
542 if (osAdapter_ == nullptr) {
543 HDF_LOGE("%{public}s: osAdapter_ is null.", __func__);
544 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
545 }
546
547 Response resp;
548 ret = TrackTime([&]() {
549 return osAdapter_->SendRequest(req, buffer, bufferSize, resp);
550 }, __func__);
551 if (ret != HDF_SUCCESS) {
552 HDF_LOGE("%{public}s: SendRequest failed, ret=%{public}d", __func__, ret);
553 return ret;
554 }
555 UpdateResponseFromOsAdapter(response, resp);
556
557 return HDF_SUCCESS;
558 }
559
Write10(const ScsiPeripheralDevice & dev,const ScsiPeripheralIORequest & request,ScsiPeripheralResponse & response)560 int32_t ScsiDdkService::Write10(const ScsiPeripheralDevice& dev,
561 const ScsiPeripheralIORequest& request, ScsiPeripheralResponse& response)
562 {
563 HDF_LOGD("ScsiDdkService::Write10 start");
564 if (!VerifyPermission(PERMISSION_NAME)) {
565 HDF_LOGE("%{public}s: no permission", __func__);
566 return SCSIPERIPHERAL_DDK_NO_PERM;
567 }
568
569 if (request.transferLength * dev.lbLength * (uint64_t)1 > MAX_TRANSFER_BYTES) {
570 HDF_LOGE("%{public}s: The value of transferLength is too large", __func__);
571 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
572 }
573
574 Request req;
575 unsigned char cdb[CDB_LENGTH_TEN];
576 BuildCdbForReadAndWrite(request, cdb, OPERATION_CODE_WRITE10);
577
578 req.commandDescriptorBlock.assign(cdb, cdb + sizeof(cdb));
579 req.dataTransferDirection = SG_DXFER_TO_DEV;
580 req.timeout = request.timeout;
581 req.devFd = dev.devFd;
582
583 std::lock_guard<std::mutex> lock(g_memMapMutex);
584 uint32_t memMapSize = request.memMapSize;
585 uint32_t bufferSize = request.transferLength * dev.lbLength;
586 if (memMapSize < bufferSize || memMapSize > MAX_MEM_MAP_SIZE) {
587 HDF_LOGE("%{public}s: memMapSize is invalid. memMapSize=%{public}d, bufferSize=%{public}d", __func__,
588 memMapSize, bufferSize);
589 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
590 }
591
592 auto buffer = static_cast<uint8_t *>(mmap(nullptr, memMapSize, PROT_READ | PROT_WRITE, MAP_SHARED,
593 dev.memMapFd, 0));
594 if (buffer == MAP_FAILED) {
595 HDF_LOGE("%{public}s: mmap failed, errno=%{public}d, memMapFd=%{public}d, memMapSize=%{public}d", __func__,
596 errno, dev.memMapFd, memMapSize);
597 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
598 }
599 MemMapFinalizer memMapFinalizer(buffer, memMapSize);
600
601 if (osAdapter_ == nullptr) {
602 HDF_LOGE("%{public}s: osAdapter_ is null.", __func__);
603 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
604 }
605
606 Response resp;
607 int32_t ret = TrackTime([&]() {
608 return osAdapter_->SendRequest(req, buffer, bufferSize, resp);
609 }, __func__);
610 if (ret != HDF_SUCCESS) {
611 HDF_LOGE("%{public}s: SendRequest failed, ret=%{public}d", __func__, ret);
612 return ret;
613 }
614
615 UpdateResponseFromOsAdapter(response, resp);
616
617 return HDF_SUCCESS;
618 }
619
Verify10(const ScsiPeripheralDevice & dev,const ScsiPeripheralVerifyRequest & request,ScsiPeripheralResponse & response)620 int32_t ScsiDdkService::Verify10(const ScsiPeripheralDevice& dev,
621 const ScsiPeripheralVerifyRequest& request, ScsiPeripheralResponse& response)
622 {
623 HDF_LOGD("ScsiDdkService::Verify10 start");
624 if (!VerifyPermission(PERMISSION_NAME)) {
625 HDF_LOGE("%{public}s: no permission", __func__);
626 return SCSIPERIPHERAL_DDK_NO_PERM;
627 }
628
629 Request req;
630 unsigned char cdb[CDB_LENGTH_TEN];
631 cdb[0] = OPERATION_CODE_VERIFY10;
632 cdb[ONE_BYTE] = request.byte1;
633 SetUint32(cdb, TWO_BYTE, request.lbAddress);
634 cdb[SIX_BYTE] = request.byte6;
635 SetUint16(cdb, SEVEN_BYTE, request.verificationLength);
636 cdb[NINE_BYTE] = request.control;
637 req.commandDescriptorBlock.assign(cdb, cdb + sizeof(cdb));
638 req.dataTransferDirection = SG_DXFER_NONE;
639 req.timeout = request.timeout;
640 req.devFd = dev.devFd;
641
642 if (osAdapter_ == nullptr) {
643 HDF_LOGE("%{public}s: osAdapter_ is null.", __func__);
644 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
645 }
646
647 Response resp;
648 int32_t ret = TrackTime([&]() {
649 return osAdapter_->SendRequest(req, nullptr, 0, resp);
650 }, __func__);
651 if (ret != HDF_SUCCESS) {
652 HDF_LOGE("%{public}s: SendRequest failed, ret=%{public}d", __func__, ret);
653 return ret;
654 }
655
656 UpdateResponseFromOsAdapter(response, resp);
657
658 return HDF_SUCCESS;
659 }
660
SendRequestByCDB(const ScsiPeripheralDevice & dev,const ScsiPeripheralRequest & request,ScsiPeripheralResponse & response)661 int32_t ScsiDdkService::SendRequestByCDB(const ScsiPeripheralDevice& dev,
662 const ScsiPeripheralRequest& request, ScsiPeripheralResponse& response)
663 {
664 HDF_LOGD("ScsiDdkService::SendRequestByCDB start");
665 if (!VerifyPermission(PERMISSION_NAME)) {
666 HDF_LOGE("%{public}s: no permission", __func__);
667 return SCSIPERIPHERAL_DDK_NO_PERM;
668 }
669
670 Request req;
671 req.commandDescriptorBlock = request.commandDescriptorBlock;
672 req.dataTransferDirection = request.dataTransferDirection;
673 req.timeout = request.timeout;
674 req.devFd = dev.devFd;
675
676 std::lock_guard<std::mutex> lock(g_memMapMutex);
677 uint32_t memMapSize = request.memMapSize;
678 if (memMapSize > MAX_MEM_MAP_SIZE) {
679 HDF_LOGE("%{public}s: memMapSize is too large. memMapSize=%{public}d, MAX_MEM_MAP_SIZE=%{public}d", __func__,
680 memMapSize, MAX_MEM_MAP_SIZE);
681 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
682 }
683 auto buffer = static_cast<uint8_t *>(mmap(nullptr, memMapSize, PROT_READ | PROT_WRITE, MAP_SHARED,
684 dev.memMapFd, 0));
685 if (buffer == MAP_FAILED) {
686 HDF_LOGE("%{public}s: mmap failed, errno=%{public}d, memMapFd=%{public}d, memMapSize=%{public}d", __func__,
687 errno, dev.memMapFd, memMapSize);
688 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
689 }
690 MemMapFinalizer memMapFinalizer(buffer, memMapSize);
691
692 if (osAdapter_ == nullptr) {
693 HDF_LOGE("%{public}s: osAdapter_ is null.", __func__);
694 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
695 }
696
697 Response resp;
698 int32_t ret = TrackTime([&]() {
699 return osAdapter_->SendRequest(req, buffer, memMapSize, resp);
700 }, __func__);
701 if (ret != HDF_SUCCESS) {
702 HDF_LOGE("%{public}s: SendRequest failed, ret=%{public}d", __func__, ret);
703 return ret;
704 }
705 UpdateResponseFromOsAdapter(response, resp);
706
707 return HDF_SUCCESS;
708 }
709
GetDeviceMemMapFd(uint16_t busNum,uint16_t devAddr,uint8_t interfaceIndex,int & memMapFd)710 int32_t ScsiDdkService::GetDeviceMemMapFd(uint16_t busNum, uint16_t devAddr, uint8_t interfaceIndex, int &memMapFd)
711 {
712 char path[PATH_LEN];
713 (void)memset_s(path, PATH_LEN, 0, PATH_LEN);
714 HDF_LOGD("scsi GetDeviceMemMapFd busNum:%{public}u, devAddr:%{public}u", busNum, devAddr);
715 int32_t ret = sprintf_s(path, sizeof(path), "%s_%03u_%03u_%u", SCSIPERIPHERAL_DEVICE_MMAP_PATH, busNum, devAddr,
716 interfaceIndex);
717 if (ret < HDF_SUCCESS) {
718 HDF_LOGE("%{public}s: sprintf_s error, ret=%{public}d", __func__, ret);
719 return SCSIPERIPHERAL_DDK_INVALID_OPERATION;
720 }
721
722 HDF_LOGD("%{public}s: path is %{public}s", __func__, path);
723 int32_t fd = TrackTime([&]() {
724 return open(path, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
725 }, __func__);
726 if (fd < 0) {
727 HDF_LOGE("%{public}s: open error, path=%{public}s, errno=%{public}d", __func__, path, errno);
728 return SCSIPERIPHERAL_DDK_IO_ERROR;
729 }
730
731 memMapFd = fd;
732 HDF_LOGD("%{public}s: memMapFd:%{public}d", __func__, memMapFd);
733
734 return HDF_SUCCESS;
735 }
736 } // V1_0
737 } // ScsiDdk
738 } // Usb
739 } // HDI
740 } // OHOS
741