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_peripheral_api.h"
17 #include <cerrno>
18 #include <iproxy_broker.h>
19 #include <memory.h>
20 #include <mutex>
21 #include <scsi/sg.h>
22 #include <securec.h>
23 #include <string>
24 #include <sys/mman.h>
25 #include <unistd.h>
26 #include <vector>
27 #include <unordered_map>
28
29 #include "edm_errors.h"
30 #include "hilog_wrapper.h"
31 #include "ipc_error_code.h"
32 #include "scsi_peripheral_types.h"
33 #include "v1_0/scsi_peripheral_ddk_service.h"
34
35 using namespace OHOS;
36 using namespace OHOS::ExternalDeviceManager;
37 namespace {
38 OHOS::sptr<OHOS::HDI::Usb::ScsiDdk::V1_0::IScsiPeripheralDdk> g_ddk = nullptr;
39 static OHOS::sptr<IRemoteObject::DeathRecipient> recipient_ = nullptr;
40 std::mutex g_mutex;
41
42 constexpr uint8_t ONE_BYTE = 1;
43 constexpr uint8_t TWO_BYTE = 2;
44 constexpr uint8_t THREE_BYTE = 3;
45 constexpr uint8_t FOUR_BYTE = 4;
46 constexpr uint8_t FIVE_BYTE = 5;
47 constexpr uint8_t SIX_BYTE = 6;
48 constexpr uint8_t SEVEN_BYTE = 7;
49 constexpr uint8_t EIGHT_BYTE = 8;
50 constexpr uint8_t FIFTEEN_BYTE = 15;
51 constexpr uint8_t EIGHT_BIT = 8;
52 constexpr uint8_t SIXTEEN_BIT = 16;
53 constexpr uint8_t TWENTY_FOUR_BIT = 24;
54 constexpr uint8_t THIRTY_TWO_BIT = 32;
55 constexpr uint8_t FORTY_BIT = 40;
56 constexpr uint8_t FORTY_EIGHT_BIT = 48;
57 constexpr uint8_t FIFTY_SIX_BIT = 56;
58 constexpr uint8_t DESCRIPTOR_TYPE_INFORMATION = 0x00;
59 constexpr uint8_t DESCRIPTOR_TYPE_COMMAND_SPECIFIC_INFORMATION = 0x01;
60 constexpr uint8_t DESCRIPTOR_TYPE_SENSE_KEY_SPECIFIC = 0x02;
61 constexpr uint8_t ADDITIONAL_LENGTH_TEN = 0x0A;
62 constexpr uint8_t ADDITIONAL_LENGTH_SIX = 0x06;
63 constexpr uint8_t VALID_BIT = 0x80;
64 constexpr uint8_t MAST_RESPONSE_CODE = 0x7F;
65 constexpr uint8_t RESPONSE_CODE_70H = 0x70;
66 constexpr uint8_t RESPONSE_CODE_71H = 0x71;
67 constexpr uint8_t RESPONSE_CODE_72H = 0x72;
68 constexpr uint8_t RESPONSE_CODE_73H = 0x73;
69 constexpr uint32_t MASK_SENSE_KEY_SPECIFIC = 0x007FFFFF;
70 } // namespace
71
72 struct ScsiPeripheral_Device {
73 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralDevice impl;
74 int memMapFd = -1;
75
ScsiPeripheral_DeviceScsiPeripheral_Device76 ScsiPeripheral_Device()
77 {
78 impl.devFd = -1;
79 impl.memMapFd = -1;
80 impl.lbLength = 0;
81 }
82 } __attribute__ ((aligned(8)));
83
NewScsiPeripheralDevice()84 ScsiPeripheral_Device *NewScsiPeripheralDevice()
85 {
86 return new ScsiPeripheral_Device;
87 }
88
DeleteScsiPeripheralDevice(ScsiPeripheral_Device ** dev)89 void DeleteScsiPeripheralDevice(ScsiPeripheral_Device **dev)
90 {
91 if (*dev != nullptr) {
92 delete *dev;
93 *dev = nullptr;
94 }
95 }
96
SetDdk(OHOS::sptr<OHOS::HDI::Usb::ScsiDdk::V1_0::IScsiPeripheralDdk> & ddk)97 void SetDdk(OHOS::sptr<OHOS::HDI::Usb::ScsiDdk::V1_0::IScsiPeripheralDdk> &ddk)
98 {
99 g_ddk = ddk;
100 }
101
TransToDdkErrCode(int32_t ret)102 static int32_t TransToDdkErrCode(int32_t ret)
103 {
104 if (ret == HDF_SUCCESS) {
105 return SCSIPERIPHERAL_DDK_SUCCESS;
106 }
107 if (ret >= OH_IPC_ERROR_CODE_BASE && ret <= OH_IPC_ERROR_CODE_MAX) {
108 return SCSIPERIPHERAL_DDK_SERVICE_ERROR;
109 }
110 return ret;
111 }
112
GetUint24(unsigned char * buf,int start)113 static inline uint32_t GetUint24(unsigned char *buf, int start)
114 {
115 return (
116 (static_cast<uint32_t>(buf[start]) << SIXTEEN_BIT) |
117 (static_cast<uint32_t>(buf[start + ONE_BYTE]) << EIGHT_BIT) |
118 (static_cast<uint32_t>(buf[start + TWO_BYTE]))
119 );
120 }
121
GetUint32(unsigned char * buf,int start)122 static inline uint32_t GetUint32(unsigned char *buf, int start)
123 {
124 return (
125 (static_cast<uint32_t>(buf[start]) << TWENTY_FOUR_BIT) |
126 (static_cast<uint32_t>(buf[start + ONE_BYTE]) << SIXTEEN_BIT) |
127 (static_cast<uint32_t>(buf[start + TWO_BYTE]) << EIGHT_BIT) |
128 (static_cast<uint32_t>(buf[start + THREE_BYTE]))
129 );
130 }
131
GetUint64(unsigned char * buf,int start)132 static inline uint64_t GetUint64(unsigned char *buf, int start)
133 {
134 return (
135 (static_cast<uint64_t>(buf[start]) << FIFTY_SIX_BIT) |
136 (static_cast<uint64_t>(buf[start + ONE_BYTE]) << FORTY_EIGHT_BIT) |
137 (static_cast<uint64_t>(buf[start + TWO_BYTE]) << FORTY_BIT) |
138 (static_cast<uint64_t>(buf[start + THREE_BYTE]) << THIRTY_TWO_BIT) |
139 (static_cast<uint64_t>(buf[start + FOUR_BYTE]) << TWENTY_FOUR_BIT) |
140 (static_cast<uint64_t>(buf[start + FIVE_BYTE]) << SIXTEEN_BIT) |
141 (static_cast<uint64_t>(buf[start + SIX_BYTE]) << EIGHT_BIT) |
142 (static_cast<uint64_t>(buf[start + SEVEN_BYTE]))
143 );
144 }
145
CopyDataToArray(const std::vector<uint8_t> & data,char * arr,uint32_t arrLen)146 static bool CopyDataToArray(const std::vector<uint8_t> &data, char *arr, uint32_t arrLen)
147 {
148 if (arr == nullptr || data.size() > arrLen) {
149 return false;
150 }
151
152 size_t i = 0;
153 while (i < data.size()) {
154 arr[i] = data[i];
155 ++i;
156 }
157 arr[arrLen - 1] = '\0';
158
159 return true;
160 }
161
CopyResponse(const OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse & srcResp,ScsiPeripheral_Response * desResp)162 static int32_t CopyResponse(const OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse &srcResp,
163 ScsiPeripheral_Response *desResp)
164 {
165 errno_t err = memcpy_s(desResp->senseData, sizeof(desResp->senseData), srcResp.senseData.data(),
166 srcResp.senseData.size());
167 if (err != EOK) {
168 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "memcpy_s failed, err=%{public}d, srcSize=%{public}zu, desSize=%{public}zu",
169 err, srcResp.senseData.size(), sizeof(desResp->senseData));
170 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
171 }
172
173 desResp->status = static_cast<ScsiPeripheral_Status>(srcResp.status);
174 desResp->maskedStatus = srcResp.maskedStatus;
175 desResp->msgStatus = srcResp.msgStatus;
176 desResp->sbLenWr = srcResp.sbLenWr;
177 desResp->hostStatus = srcResp.hostStatus;
178 desResp->driverStatus = srcResp.driverStatus;
179 desResp->resId = srcResp.resId;
180 desResp->duration = srcResp.duration;
181
182 return SCSIPERIPHERAL_DDK_SUCCESS;
183 }
184
ToHdi(ScsiPeripheral_IORequest * request,OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralIORequest & hdiRequest)185 static void ToHdi(ScsiPeripheral_IORequest *request, OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralIORequest &hdiRequest)
186 {
187 hdiRequest.lbAddress = request->lbAddress;
188 hdiRequest.transferLength = request->transferLength;
189 hdiRequest.control = request->control;
190 hdiRequest.byte1 = request->byte1;
191 hdiRequest.byte6 = request->byte6;
192 hdiRequest.memMapSize = request->data->size;
193 hdiRequest.timeout = request->timeout;
194 }
195
ParseDescriptorFormatSense(uint8_t * senseData,uint8_t senseDataLen,ScsiPeripheral_BasicSenseInfo * senseInfo)196 static int32_t ParseDescriptorFormatSense(uint8_t *senseData, uint8_t senseDataLen,
197 ScsiPeripheral_BasicSenseInfo *senseInfo)
198 {
199 if (senseDataLen < SCSIPERIPHERAL_MIN_DESCRIPTOR_FORMAT_SENSE) {
200 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "sense data len is invalid");
201 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
202 }
203
204 uint8_t additionalSenseLen = senseData[EIGHT_BYTE - 1];
205 if (senseDataLen > additionalSenseLen + EIGHT_BYTE) {
206 senseDataLen = additionalSenseLen + EIGHT_BYTE;
207 }
208
209 uint8_t idx;
210 uint8_t descLen;
211
212 for (idx = EIGHT_BYTE; idx < senseDataLen; idx += descLen + TWO_BYTE) {
213 uint8_t descType = senseData[idx];
214 descLen = senseData[idx + 1];
215
216 if (idx + descLen + TWO_BYTE > senseDataLen) {
217 break;
218 }
219
220 switch (descType) {
221 case DESCRIPTOR_TYPE_INFORMATION:
222 if (descLen == ADDITIONAL_LENGTH_TEN) {
223 senseInfo->valid = senseData[idx + TWO_BYTE] & VALID_BIT;
224 senseInfo->information = GetUint64(senseData, idx + FOUR_BYTE);
225 }
226 break;
227 case DESCRIPTOR_TYPE_COMMAND_SPECIFIC_INFORMATION:
228 if (descLen == ADDITIONAL_LENGTH_TEN) {
229 senseInfo->commandSpecific = GetUint64(senseData, idx + FOUR_BYTE);
230 }
231 break;
232 case DESCRIPTOR_TYPE_SENSE_KEY_SPECIFIC:
233 if (descLen == ADDITIONAL_LENGTH_SIX) {
234 senseInfo->sksv = senseData[idx + FOUR_BYTE] & VALID_BIT;
235 senseInfo->senseKeySpecific = GetUint24(senseData, idx + FOUR_BYTE) & MASK_SENSE_KEY_SPECIFIC;
236 }
237 break;
238 default:
239 break;
240 }
241 }
242
243 return SCSIPERIPHERAL_DDK_SUCCESS;
244 }
245
ParseFixedFormatSense(uint8_t * senseData,uint8_t senseDataLen,ScsiPeripheral_BasicSenseInfo * senseInfo)246 static int32_t ParseFixedFormatSense(uint8_t *senseData, uint8_t senseDataLen, ScsiPeripheral_BasicSenseInfo *senseInfo)
247 {
248 if (senseDataLen < SCSIPERIPHERAL_MIN_FIXED_FORMAT_SENSE) {
249 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "sense data len is invalid");
250 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
251 }
252
253 senseInfo->valid = senseData[0] & VALID_BIT;
254
255 if (senseInfo->valid) {
256 senseInfo->information = GetUint32(senseData, THREE_BYTE);
257 }
258 senseInfo->commandSpecific = GetUint32(senseData, EIGHT_BYTE);
259 senseInfo->sksv = senseData[FIFTEEN_BYTE] & VALID_BIT;
260 senseInfo->senseKeySpecific = GetUint24(senseData, FIFTEEN_BYTE) & MASK_SENSE_KEY_SPECIFIC;
261
262 return SCSIPERIPHERAL_DDK_SUCCESS;
263 }
264
265 class ScsiPeripheralDeathRecipient : public IRemoteObject::DeathRecipient {
266 public:
267 void OnRemoteDied(const wptr<IRemoteObject> &object) override;
268 };
269
OnRemoteDied(const wptr<IRemoteObject> & object)270 void ScsiPeripheralDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
271 {
272 std::lock_guard<std::mutex> lock(g_mutex);
273 EDM_LOGI(MODULE_SCSIPERIPHERAL_DDK, "scsi_ddk remote died");
274 if (g_ddk == nullptr) {
275 return;
276 }
277 auto remote = OHOS::HDI::hdi_objcast<OHOS::HDI::Usb::ScsiDdk::V1_0::IScsiPeripheralDdk>(g_ddk);
278 remote->RemoveDeathRecipient(recipient_);
279 recipient_.clear();
280 g_ddk = nullptr;
281 EDM_LOGI(MODULE_SCSIPERIPHERAL_DDK, "remove death recipient success");
282 }
283
OH_ScsiPeripheral_Init(void)284 int32_t OH_ScsiPeripheral_Init(void)
285 {
286 auto ddk = OHOS::HDI::Usb::ScsiDdk::V1_0::IScsiPeripheralDdk::Get();
287 SetDdk(ddk);
288 if (g_ddk == nullptr) {
289 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "get ddk failed");
290 return SCSIPERIPHERAL_DDK_INIT_ERROR;
291 }
292 recipient_ = new ScsiPeripheralDeathRecipient();
293 sptr<IRemoteObject> remote = OHOS::HDI::hdi_objcast<OHOS::HDI::Usb::ScsiDdk::V1_0::IScsiPeripheralDdk>(g_ddk);
294 if (!remote->AddDeathRecipient(recipient_)) {
295 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "add DeathRecipient failed");
296 return SCSIPERIPHERAL_DDK_INIT_ERROR;
297 }
298 return TransToDdkErrCode(g_ddk->Init());
299 }
300
OH_ScsiPeripheral_Release(void)301 int32_t OH_ScsiPeripheral_Release(void)
302 {
303 if (g_ddk == nullptr) {
304 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "ddk is null");
305 return SCSIPERIPHERAL_DDK_INIT_ERROR;
306 }
307 int32_t ret = g_ddk->Release();
308 g_ddk.clear();
309
310 return TransToDdkErrCode(ret);
311 }
312
OH_ScsiPeripheral_Open(uint64_t deviceId,uint8_t interfaceIndex,ScsiPeripheral_Device ** dev)313 int32_t OH_ScsiPeripheral_Open(uint64_t deviceId, uint8_t interfaceIndex, ScsiPeripheral_Device **dev)
314 {
315 if (g_ddk == nullptr) {
316 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
317 return SCSIPERIPHERAL_DDK_INIT_ERROR;
318 }
319 if (dev == nullptr) {
320 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
321 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
322 }
323
324 *dev = NewScsiPeripheralDevice();
325 if (*dev == nullptr) {
326 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "malloc failed, errno=%{public}d", errno);
327 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
328 }
329
330 return TransToDdkErrCode(g_ddk->Open(deviceId, interfaceIndex, (*dev)->impl, (*dev)->memMapFd));
331 }
332
OH_ScsiPeripheral_Close(ScsiPeripheral_Device ** dev)333 int32_t OH_ScsiPeripheral_Close(ScsiPeripheral_Device **dev)
334 {
335 if (g_ddk == nullptr) {
336 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
337 return SCSIPERIPHERAL_DDK_INIT_ERROR;
338 }
339 if (dev == nullptr || *dev == nullptr) {
340 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
341 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
342 }
343
344 int32_t ret = TransToDdkErrCode(g_ddk->Close((*dev)->impl));
345 if (close((*dev)->memMapFd)) {
346 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "close memMapFd failed, errno=%{public}d", errno);
347 if (ret == SCSIPERIPHERAL_DDK_SUCCESS) {
348 ret = SCSIPERIPHERAL_DDK_IO_ERROR;
349 }
350 }
351 DeleteScsiPeripheralDevice(dev);
352 return ret;
353 }
354
OH_ScsiPeripheral_TestUnitReady(ScsiPeripheral_Device * dev,ScsiPeripheral_TestUnitReadyRequest * request,ScsiPeripheral_Response * response)355 int32_t OH_ScsiPeripheral_TestUnitReady(ScsiPeripheral_Device *dev, ScsiPeripheral_TestUnitReadyRequest *request,
356 ScsiPeripheral_Response *response)
357 {
358 if (g_ddk == nullptr) {
359 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
360 return SCSIPERIPHERAL_DDK_INIT_ERROR;
361 }
362 if (dev == nullptr || request == nullptr || response == nullptr) {
363 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
364 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
365 }
366
367 auto hdiRequest = reinterpret_cast<OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralTestUnitReadyRequest *>(request);
368 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse hdiResponse;
369 hdiResponse.senseData.resize(sizeof(response->senseData));
370 int32_t ret = TransToDdkErrCode(g_ddk->TestUnitReady(dev->impl, *hdiRequest, hdiResponse));
371 if (ret != SCSIPERIPHERAL_DDK_SUCCESS) {
372 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "test unit ready failed");
373 return ret;
374 }
375
376 return CopyResponse(hdiResponse, response);
377 }
378
OH_ScsiPeripheral_Inquiry(ScsiPeripheral_Device * dev,ScsiPeripheral_InquiryRequest * request,ScsiPeripheral_InquiryInfo * inquiryInfo,ScsiPeripheral_Response * response)379 int32_t OH_ScsiPeripheral_Inquiry(ScsiPeripheral_Device *dev, ScsiPeripheral_InquiryRequest *request,
380 ScsiPeripheral_InquiryInfo *inquiryInfo, ScsiPeripheral_Response *response)
381 {
382 if (g_ddk == nullptr) {
383 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
384 return SCSIPERIPHERAL_DDK_INIT_ERROR;
385 }
386 if (dev == nullptr || request == nullptr || inquiryInfo == nullptr || inquiryInfo->data == nullptr ||
387 response == nullptr) {
388 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
389 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
390 }
391
392 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralInquiryRequest hdiInquiryRequest;
393 hdiInquiryRequest.pageCode = request->pageCode;
394 hdiInquiryRequest.allocationLength = request->allocationLength;
395 hdiInquiryRequest.control = request->control;
396 hdiInquiryRequest.byte1 = request->byte1;
397 hdiInquiryRequest.memMapSize = inquiryInfo->data->size;
398 hdiInquiryRequest.timeout = request->timeout;
399
400 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralInquiryInfo hdiInquiryInfo;
401 hdiInquiryInfo.idVendor.resize(SCSIPERIPHERAL_VENDOR_ID_LEN);
402 hdiInquiryInfo.idProduct.resize(sizeof(inquiryInfo->idProduct));
403 hdiInquiryInfo.revProduct.resize(sizeof(inquiryInfo->revProduct));
404 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse hdiResponse;
405 hdiResponse.senseData.resize(sizeof(response->senseData));
406
407 int32_t ret = TransToDdkErrCode(g_ddk->Inquiry(dev->impl, hdiInquiryRequest, hdiInquiryInfo, hdiResponse));
408 if (ret != SCSIPERIPHERAL_DDK_SUCCESS) {
409 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "inquiry failed");
410 return ret;
411 }
412
413 inquiryInfo->deviceType = hdiInquiryInfo.deviceType;
414 if (!CopyDataToArray(hdiInquiryInfo.idVendor, inquiryInfo->idVendor, sizeof(inquiryInfo->idVendor))) {
415 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "copy idVendor failed");
416 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
417 }
418 if (!CopyDataToArray(hdiInquiryInfo.idProduct, inquiryInfo->idProduct, sizeof(inquiryInfo->idProduct))) {
419 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "copy idProduct failed");
420 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
421 }
422 if (!CopyDataToArray(hdiInquiryInfo.revProduct, inquiryInfo->revProduct, sizeof(inquiryInfo->revProduct))) {
423 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "copy revProduct failed");
424 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
425 }
426 inquiryInfo->data->transferredLength = static_cast<uint32_t>(hdiResponse.transferredLength);
427
428 return CopyResponse(hdiResponse, response);
429 }
430
OH_ScsiPeripheral_ReadCapacity10(ScsiPeripheral_Device * dev,ScsiPeripheral_ReadCapacityRequest * request,ScsiPeripheral_CapacityInfo * capacityInfo,ScsiPeripheral_Response * response)431 int32_t OH_ScsiPeripheral_ReadCapacity10(ScsiPeripheral_Device *dev, ScsiPeripheral_ReadCapacityRequest *request,
432 ScsiPeripheral_CapacityInfo *capacityInfo, ScsiPeripheral_Response *response)
433 {
434 if (g_ddk == nullptr) {
435 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
436 return SCSIPERIPHERAL_DDK_INIT_ERROR;
437 }
438 if (dev == nullptr || request == nullptr || capacityInfo == nullptr || response == nullptr) {
439 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
440 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
441 }
442
443 auto hdiRequest = reinterpret_cast<OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralReadCapacityRequest *>(request);
444 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralCapacityInfo hdiCapacityInfo;
445 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse hdiResponse;
446 hdiResponse.senseData.resize(sizeof(response->senseData));
447
448 int32_t ret = TransToDdkErrCode(g_ddk->ReadCapacity10(dev->impl, *hdiRequest, hdiCapacityInfo,
449 hdiResponse));
450 if (ret != SCSIPERIPHERAL_DDK_SUCCESS) {
451 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "readcapacity10 failed");
452 return ret;
453 }
454
455 capacityInfo->lbAddress = hdiCapacityInfo.lbAddress;
456 capacityInfo->lbLength = hdiCapacityInfo.lbLength;
457
458 return CopyResponse(hdiResponse, response);
459 }
460
OH_ScsiPeripheral_RequestSense(ScsiPeripheral_Device * dev,ScsiPeripheral_RequestSenseRequest * request,ScsiPeripheral_Response * response)461 int32_t OH_ScsiPeripheral_RequestSense(ScsiPeripheral_Device *dev, ScsiPeripheral_RequestSenseRequest *request,
462 ScsiPeripheral_Response *response)
463 {
464 if (g_ddk == nullptr) {
465 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
466 return SCSIPERIPHERAL_DDK_INIT_ERROR;
467 }
468 if (dev == nullptr || request == nullptr || response == nullptr) {
469 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
470 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
471 }
472
473 auto hdiRequest = reinterpret_cast<OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralRequestSenseRequest *>(request);
474 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse hdiResponse;
475 hdiResponse.senseData.resize(sizeof(response->senseData));
476 int32_t ret = TransToDdkErrCode(g_ddk->RequestSense(dev->impl, *hdiRequest, hdiResponse));
477 if (ret != SCSIPERIPHERAL_DDK_SUCCESS) {
478 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "request sense failed");
479 return ret;
480 }
481
482 return CopyResponse(hdiResponse, response);
483 }
484
OH_ScsiPeripheral_Read10(ScsiPeripheral_Device * dev,ScsiPeripheral_IORequest * request,ScsiPeripheral_Response * response)485 int32_t OH_ScsiPeripheral_Read10(ScsiPeripheral_Device *dev, ScsiPeripheral_IORequest *request,
486 ScsiPeripheral_Response *response)
487 {
488 EDM_LOGD(MODULE_SCSIPERIPHERAL_DDK, "Read10 start");
489 if (g_ddk == nullptr) {
490 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
491 return SCSIPERIPHERAL_DDK_INIT_ERROR;
492 }
493 if (dev == nullptr || request == nullptr || request->data ==nullptr || response == nullptr) {
494 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
495 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
496 }
497
498 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralIORequest hdiIORequest;
499 ToHdi(request, hdiIORequest);
500 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse hdiResponse;
501 hdiResponse.senseData.resize(sizeof(response->senseData));
502
503 int32_t ret = TransToDdkErrCode(g_ddk->Read10(dev->impl, hdiIORequest, hdiResponse));
504 if (ret != SCSIPERIPHERAL_DDK_SUCCESS) {
505 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "read10 failed");
506 return ret;
507 }
508
509 request->data->transferredLength = static_cast<uint32_t>(hdiResponse.transferredLength);
510
511 return CopyResponse(hdiResponse, response);
512 }
513
OH_ScsiPeripheral_Write10(ScsiPeripheral_Device * dev,ScsiPeripheral_IORequest * request,ScsiPeripheral_Response * response)514 int32_t OH_ScsiPeripheral_Write10(ScsiPeripheral_Device *dev, ScsiPeripheral_IORequest *request,
515 ScsiPeripheral_Response *response)
516 {
517 if (g_ddk == nullptr) {
518 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
519 return SCSIPERIPHERAL_DDK_INIT_ERROR;
520 }
521 if (dev == nullptr || request == nullptr || request->data ==nullptr || response == nullptr) {
522 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
523 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
524 }
525
526 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralIORequest hdiIORequest;
527 ToHdi(request, hdiIORequest);
528 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse hdiResponse;
529 hdiResponse.senseData.resize(sizeof(response->senseData));
530
531 int32_t ret = TransToDdkErrCode(g_ddk->Write10(dev->impl, hdiIORequest, hdiResponse));
532 if (ret != SCSIPERIPHERAL_DDK_SUCCESS) {
533 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "write10 failed");
534 return ret;
535 }
536
537 request->data->transferredLength = static_cast<uint32_t>(hdiResponse.transferredLength);
538
539 return CopyResponse(hdiResponse, response);
540 }
541
OH_ScsiPeripheral_Verify10(ScsiPeripheral_Device * dev,ScsiPeripheral_VerifyRequest * request,ScsiPeripheral_Response * response)542 int32_t OH_ScsiPeripheral_Verify10(ScsiPeripheral_Device *dev, ScsiPeripheral_VerifyRequest *request,
543 ScsiPeripheral_Response *response)
544 {
545 if (g_ddk == nullptr) {
546 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
547 return SCSIPERIPHERAL_DDK_INIT_ERROR;
548 }
549 if (dev == nullptr || request == nullptr || response == nullptr) {
550 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
551 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
552 }
553
554 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralVerifyRequest hdiVerifyRequest;
555 hdiVerifyRequest.lbAddress = request->lbAddress;
556 hdiVerifyRequest.verificationLength = request->verificationLength;
557 hdiVerifyRequest.control = request->control;
558 hdiVerifyRequest.byte1 = request->byte1;
559 hdiVerifyRequest.byte6 = request->byte6;
560 hdiVerifyRequest.timeout = request->timeout;
561 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse hdiResponse;
562 hdiResponse.senseData.resize(sizeof(response->senseData));
563
564 int32_t ret = TransToDdkErrCode(g_ddk->Verify10(dev->impl, hdiVerifyRequest, hdiResponse));
565 if (ret != SCSIPERIPHERAL_DDK_SUCCESS) {
566 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "verify10 failed");
567 return ret;
568 }
569
570 return CopyResponse(hdiResponse, response);
571 }
572
OH_ScsiPeripheral_SendRequestByCdb(ScsiPeripheral_Device * dev,ScsiPeripheral_Request * request,ScsiPeripheral_Response * response)573 int32_t OH_ScsiPeripheral_SendRequestByCdb(ScsiPeripheral_Device *dev, ScsiPeripheral_Request *request,
574 ScsiPeripheral_Response *response)
575 {
576 EDM_LOGD(MODULE_SCSIPERIPHERAL_DDK, "SendRequestByCDB start");
577 if (g_ddk == nullptr) {
578 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "invalid obj");
579 return SCSIPERIPHERAL_DDK_INIT_ERROR;
580 }
581 if (dev == nullptr || request == nullptr || request->data ==nullptr || response == nullptr) {
582 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
583 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
584 }
585 if (request->cdbLength == 0) {
586 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "cdb length is 0");
587 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
588 }
589
590 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralRequest hdiRequest;
591 hdiRequest.commandDescriptorBlock.assign(request->commandDescriptorBlock,
592 request->commandDescriptorBlock + request->cdbLength);
593 hdiRequest.dataTransferDirection = request->dataTransferDirection;
594 hdiRequest.memMapSize = request->data->size;
595 hdiRequest.timeout = request->timeout;
596 OHOS::HDI::Usb::ScsiDdk::V1_0::ScsiPeripheralResponse hdiResponse;
597 hdiResponse.senseData.resize(sizeof(response->senseData));
598
599 int32_t ret = TransToDdkErrCode(g_ddk->SendRequestByCDB(dev->impl, hdiRequest, hdiResponse));
600 if (ret != SCSIPERIPHERAL_DDK_SUCCESS) {
601 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "send request by cdb failed");
602 return ret;
603 }
604
605 request->data->transferredLength = static_cast<uint32_t>(hdiResponse.transferredLength);
606
607 return CopyResponse(hdiResponse, response);
608 }
609
OH_ScsiPeripheral_CreateDeviceMemMap(ScsiPeripheral_Device * dev,size_t size,ScsiPeripheral_DeviceMemMap ** devMmap)610 int32_t OH_ScsiPeripheral_CreateDeviceMemMap(ScsiPeripheral_Device *dev, size_t size,
611 ScsiPeripheral_DeviceMemMap **devMmap)
612 {
613 if (dev == nullptr || devMmap == nullptr) {
614 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
615 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
616 }
617 if (dev->memMapFd < 0) {
618 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "memMapFd is invalid");
619 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
620 }
621
622 ftruncate(dev->memMapFd, size);
623 auto buffer = static_cast<uint8_t *>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, dev->memMapFd, 0));
624 if (buffer == MAP_FAILED) {
625 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "mmap failed, errno=%{public}d", errno);
626 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
627 }
628
629 ScsiPeripheral_DeviceMemMap *memMap = new ScsiPeripheral_DeviceMemMap({buffer, size, 0, size, 0});
630 if (memMap == nullptr) {
631 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "alloc dev mem failed, errno=%{public}d", errno);
632 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
633 }
634
635 *devMmap = memMap;
636 return SCSIPERIPHERAL_DDK_SUCCESS;
637 }
638
OH_ScsiPeripheral_DestroyDeviceMemMap(ScsiPeripheral_DeviceMemMap * devMmap)639 int32_t OH_ScsiPeripheral_DestroyDeviceMemMap(ScsiPeripheral_DeviceMemMap *devMmap)
640 {
641 if (devMmap == nullptr) {
642 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "devMmap is nullptr");
643 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
644 }
645
646 if (munmap(devMmap->address, devMmap->size) != 0) {
647 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "munmap failed, errno=%{public}d", errno);
648 return SCSIPERIPHERAL_DDK_MEMORY_ERROR;
649 }
650 delete devMmap;
651 devMmap = nullptr;
652 return SCSIPERIPHERAL_DDK_SUCCESS;
653 }
654
OH_ScsiPeripheral_ParseBasicSenseInfo(uint8_t * senseData,uint8_t senseDataLen,ScsiPeripheral_BasicSenseInfo * senseInfo)655 int32_t OH_ScsiPeripheral_ParseBasicSenseInfo(uint8_t *senseData, uint8_t senseDataLen,
656 ScsiPeripheral_BasicSenseInfo *senseInfo)
657 {
658 if (senseData == nullptr || senseInfo == nullptr) {
659 EDM_LOGE(MODULE_SCSIPERIPHERAL_DDK, "param is null");
660 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
661 }
662
663 senseInfo->responseCode = senseData[0] & MAST_RESPONSE_CODE;
664
665 if (senseInfo->responseCode == RESPONSE_CODE_70H || senseInfo->responseCode == RESPONSE_CODE_71H) {
666 return ParseFixedFormatSense(senseData, senseDataLen, senseInfo);
667 } else if (senseInfo->responseCode == RESPONSE_CODE_72H || senseInfo->responseCode == RESPONSE_CODE_73H) {
668 return ParseDescriptorFormatSense(senseData, senseDataLen, senseInfo);
669 }
670
671 return SCSIPERIPHERAL_DDK_INVALID_PARAMETER;
672 }
673