79 } |
77 } |
80 |
78 |
81 TUint32 TMediaWriteMan::GetPacketLength() const |
79 TUint32 TMediaWriteMan::GetPacketLength() const |
82 { |
80 { |
83 // KMaxBufSize or the MediaWriteSize, whichever is smallest. |
81 // KMaxBufSize or the MediaWriteSize, whichever is smallest. |
84 TUint32 thisLength = (iBytesRemain > KMaxBufSize) ? KMaxBufSize : iBytesRemain; |
82 TUint32 thisLength = (iBytesRemain > KMaxBufSize) ? KMaxBufSize : iBytesRemain; |
85 thisLength = (thisLength > iMediaWriteSize) ? iMediaWriteSize : thisLength; |
83 thisLength = (thisLength > iMediaWriteSize) ? iMediaWriteSize : thisLength; |
86 return thisLength; |
84 return thisLength; |
87 } |
85 } |
88 |
86 |
89 |
87 |
90 /** |
88 /** |
91 Creates the CScsiProtocol object. Called during controller initialisation. |
89 Creates the CScsiProtocol object. Called during controller initialisation. |
92 |
90 |
93 @param aDriveManager reference to the drive manager object |
91 @param aDriveManager reference to the drive manager object |
94 */ |
92 */ |
95 CScsiServerProtocol* CScsiServerProtocol::NewL(CDriveManager& aDriveManager) |
93 CScsiServerProtocol* CScsiServerProtocol::NewL(CDriveManager& aDriveManager) |
96 { |
94 { |
97 __MSFNSLOG |
95 CScsiServerProtocol* self = new (ELeave) CScsiServerProtocol(aDriveManager); |
98 CScsiServerProtocol* self = new (ELeave) CScsiServerProtocol(aDriveManager); |
96 CleanupStack::PushL(self); |
99 CleanupStack::PushL(self); |
97 self->ConstructL(); |
100 self->ConstructL(); |
98 CleanupStack::Pop(); |
101 CleanupStack::Pop(); |
99 return self; |
102 return self; |
100 } |
103 } |
|
104 |
101 |
105 #ifdef MSDC_TESTMODE |
102 #ifdef MSDC_TESTMODE |
106 CScsiServerProtocol* CScsiServerProtocol::NewL(CDriveManager& aDriveManager, TTestParser* aTestParser) |
103 CScsiServerProtocol* CScsiServerProtocol::NewL(CDriveManager& aDriveManager, TTestParser* aTestParser) |
107 { |
104 { |
108 __MSFNSLOG |
105 CScsiServerProtocol* self = new (ELeave) CScsiServerProtocol(aDriveManager, aTestParser); |
109 CScsiServerProtocol* self = new (ELeave) CScsiServerProtocol(aDriveManager, aTestParser); |
106 CleanupStack::PushL(self); |
110 CleanupStack::PushL(self); |
107 self->ConstructL(); |
111 self->ConstructL(); |
108 CleanupStack::Pop(); |
112 CleanupStack::Pop(); |
109 return self; |
113 return self; |
110 } |
114 } |
|
115 #endif |
111 #endif |
116 |
112 |
117 |
113 |
118 /** |
114 /** |
119 c'tor |
115 c'tor |
120 |
116 |
121 @param aDriveManager reference to the drive manager object |
117 @param aDriveManager reference to the drive manager object |
122 */ |
118 */ |
123 CScsiServerProtocol::CScsiServerProtocol(CDriveManager& aDriveManager) |
119 CScsiServerProtocol::CScsiServerProtocol(CDriveManager& aDriveManager) |
124 : iDriveManager(aDriveManager) |
120 : iDriveManager(aDriveManager) |
125 { |
121 { |
126 __MSFNLOG |
122 iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten); |
127 |
123 iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead); |
128 iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten); |
124 |
129 iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead); |
125 for (TUint i = 0; i < KUsbMsMaxDrives; i++) |
130 |
126 { |
131 for (TUint i = 0; i < KUsbMsMaxDrives; i++) |
127 iBytesRead[i] = 0; |
132 { |
128 iBytesWritten[i] = 0; |
133 iBytesRead[i] = 0; |
129 } |
134 iBytesWritten[i] = 0; |
130 } |
135 } |
|
136 } |
|
137 |
131 |
138 #ifdef MSDC_TESTMODE |
132 #ifdef MSDC_TESTMODE |
139 CScsiServerProtocol::CScsiServerProtocol(CDriveManager& aDriveManager, TTestParser* aTestParser) |
133 CScsiServerProtocol::CScsiServerProtocol(CDriveManager& aDriveManager, TTestParser* aTestParser) |
140 : iDriveManager(aDriveManager), |
134 : iDriveManager(aDriveManager), |
141 iTestParser(aTestParser) |
135 iTestParser(aTestParser) |
142 { |
136 { |
143 __MSFNLOG |
137 iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten); |
144 |
138 iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead); |
145 iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten); |
139 |
146 iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead); |
140 for (TUint i = 0; i < KUsbMsMaxDrives; i++) |
147 |
141 { |
148 for (TUint i = 0; i < KUsbMsMaxDrives; i++) |
142 iBytesRead[i] = 0; |
149 { |
143 iBytesWritten[i] = 0; |
150 iBytesRead[i] = 0; |
144 } |
151 iBytesWritten[i] = 0; |
145 } |
152 } |
|
153 } |
|
154 #endif |
146 #endif |
155 |
147 |
156 |
148 |
157 CScsiServerProtocol::~CScsiServerProtocol() |
149 CScsiServerProtocol::~CScsiServerProtocol() |
158 { |
150 { |
159 __MSFNLOG |
|
160 iDataBuf.Close(); |
151 iDataBuf.Close(); |
161 delete iWriteTransferPublisher; |
152 delete iWriteTransferPublisher; |
162 delete iReadTransferPublisher; |
153 delete iReadTransferPublisher; |
163 } |
154 } |
164 |
155 |
165 |
156 |
166 void CScsiServerProtocol::ConstructL() |
157 void CScsiServerProtocol::ConstructL() |
167 { |
158 { |
168 __MSFNLOG |
159 } |
169 } |
|
170 |
160 |
171 |
161 |
172 /** |
162 /** |
173 Associates the transport with the protocol. Called during initialisation of the controller. |
163 Associates the transport with the protocol. Called during initialisation of the controller. |
174 |
164 |
175 @param aTransport pointer to the transport object |
165 @param aTransport pointer to the transport object |
176 */ |
166 */ |
177 void CScsiServerProtocol::RegisterTransport(MDeviceTransport* aTransport) |
167 void CScsiServerProtocol::RegisterTransport(MDeviceTransport* aTransport) |
178 { |
168 { |
179 __MSFNLOG |
169 iTransport = aTransport; |
180 iTransport = aTransport; |
170 } |
181 } |
|
182 |
171 |
183 |
172 |
184 /** |
173 /** |
185 Called by the Transport when it detects that the USB device is either running |
174 Called by the Transport when it detects that the USB device is either running |
186 at High Speed or is at least capable of HS operation. The Protocol can use this |
175 at High Speed or is at least capable of HS operation. The Protocol can use this |
211 @param aData |
198 @param aData |
212 |
199 |
213 @return ETrue if command was decoded and executed successfully |
200 @return ETrue if command was decoded and executed successfully |
214 */ |
201 */ |
215 TBool CScsiServerProtocol::DecodePacket(TPtrC8& aData, TUint8 aLun) |
202 TBool CScsiServerProtocol::DecodePacket(TPtrC8& aData, TUint8 aLun) |
216 { |
203 { |
217 __MSFNLOG |
|
218 TScsiServerReq* cdb = NULL; |
204 TScsiServerReq* cdb = NULL; |
219 TRAPD(err, cdb = cdb->CreateL(static_cast<TScsiServerReq::TOperationCode>(aData[0]), aData)); |
205 TRAPD(err, cdb = cdb->CreateL(static_cast<TScsiServerReq::TOperationCode>(aData[0]), aData)); |
220 |
206 |
221 TBool decodeGood = EFalse; |
207 TBool decodeGood = EFalse; |
222 if (err == KErrNotSupported) |
208 if (err == KErrNotSupported) |
223 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode); |
209 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode); |
224 else if (err != KErrNone) |
210 else if (err != KErrNone) |
225 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand, TSenseInfo::EInsufficientRes); |
211 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand, TSenseInfo::EInsufficientRes); |
226 else if (cdb->iNaca) // Check the CONTROL byte |
212 else if (cdb->iNaca) // Check the CONTROL byte |
227 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
213 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
228 else if (cdb->iLink) |
214 else if (cdb->iLink) |
229 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
215 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
230 else |
216 else |
231 { |
217 { |
232 TScsiServerReq::TOperationCode operationCode = cdb->iOperationCode; |
218 TScsiServerReq::TOperationCode operationCode = cdb->iOperationCode; |
330 iTestParser->ClrSenseError(); |
315 iTestParser->ClrSenseError(); |
331 return NULL; |
316 return NULL; |
332 } |
317 } |
333 #endif |
318 #endif |
334 |
319 |
335 CMassStorageDrive* drive = iDriveManager.Drive(iLun); |
320 CMassStorageDrive* drive = iDriveManager.Drive(iLun); |
336 CMassStorageDrive::TMountState mountState = drive->MountState(); |
321 CMassStorageDrive::TMountState mountState = drive->MountState(); |
337 |
322 |
338 if (mountState == CMassStorageDrive::EDisconnected || mountState == CMassStorageDrive::EConnecting) |
323 if (mountState == CMassStorageDrive::EDisconnected || mountState == CMassStorageDrive::EConnecting) |
339 { |
324 { |
340 __PRINT(_L("Drive disconnected\n")); |
325 __PRINT(_L("Drive disconnected\n")); |
341 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
326 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
342 TSenseInfo::EMediaNotPresent); |
327 TSenseInfo::EMediaNotPresent); |
343 return NULL; |
328 return NULL; |
344 } |
329 } |
345 |
330 |
346 TLocalDriveRef::TDriveState state = drive->CheckDriveState(); |
331 TLocalDriveRef::TDriveState state = drive->CheckDriveState(); |
347 if (state == TLocalDriveRef::EMediaNotPresent || state == TLocalDriveRef::ELocked) |
332 if (state == TLocalDriveRef::EMediaNotPresent || state == TLocalDriveRef::ELocked) |
348 { |
333 { |
349 __PRINT1(_L("Media not present or locked. (state =0x%X)\n"),state); |
334 __PRINT1(_L("Media not present or locked. (state =0x%X)\n"),state); |
350 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
335 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
351 return NULL; |
336 return NULL; |
352 } |
337 } |
353 |
338 |
354 if (drive->IsMediaChanged(ETrue)) //reset "media changed" status |
339 if (drive->IsMediaChanged(ETrue)) //reset "media changed" status |
355 { |
340 { |
356 __PRINT(_L("Media was changed\n")); |
341 __PRINT(_L("Media was changed\n")); |
357 // SAM-2 Section 5.9.5 Unit Attention Condition |
342 // SAM-2 Section 5.9.5 Unit Attention Condition |
358 iSenseInfo.SetSense(TSenseInfo::EUnitAttention, TSenseInfo::ENotReadyToReadyChange); |
343 iSenseInfo.SetSense(TSenseInfo::EUnitAttention, TSenseInfo::ENotReadyToReadyChange); |
359 iDriveManager.Connect(iLun); //publish event to USB app |
344 iDriveManager.Connect(iLun); //publish event to USB app |
360 return NULL; |
345 return NULL; |
361 } |
346 } |
362 |
347 |
363 if (mountState == CMassStorageDrive::EDisconnecting) |
348 if (mountState == CMassStorageDrive::EDisconnecting) |
364 { |
349 { |
365 __PRINT(_L("Drive disconnecting\n")); |
350 __PRINT(_L("Drive disconnecting\n")); |
366 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
351 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
367 TSenseInfo::EMediaNotPresent); |
352 TSenseInfo::EMediaNotPresent); |
368 return NULL; |
353 return NULL; |
369 } |
354 } |
370 |
355 |
371 return drive; |
356 return drive; |
372 } |
357 } |
373 |
358 |
374 |
359 |
375 /** |
360 /** |
376 Command Parser for the UNIT READY command (0x00) |
361 Command Parser for the UNIT READY command (0x00) |
377 |
362 |
378 @param aLun Logic unit number |
363 @param aLun Logic unit number |
379 @return ETrue if successful, |
364 @return ETrue if successful, |
380 */ |
365 */ |
381 TBool CScsiServerProtocol::HandleUnitReady() |
366 TBool CScsiServerProtocol::HandleUnitReady() |
382 { |
367 { |
383 __MSFNLOG |
368 return GetCheckDrive() ? ETrue : EFalse; |
384 return GetCheckDrive() ? ETrue : EFalse; |
369 } |
385 } |
|
386 |
370 |
387 |
371 |
388 /** |
372 /** |
389 Command Parser for the REQUEST SENSE command (0x03) |
373 Command Parser for the REQUEST SENSE command (0x03) |
390 |
374 |
391 @return ETrue if successful, |
375 @return ETrue if successful, |
392 */ |
376 */ |
393 TBool CScsiServerProtocol::HandleRequestSense(const TScsiServerReq& aRequest) |
377 TBool CScsiServerProtocol::HandleRequestSense(const TScsiServerReq& aRequest) |
394 { |
378 { |
395 __MSFNLOG |
|
396 const TScsiServerRequestSenseReq request = static_cast<const TScsiServerRequestSenseReq&>(aRequest); |
379 const TScsiServerRequestSenseReq request = static_cast<const TScsiServerRequestSenseReq&>(aRequest); |
397 __PRINT1(_L("length = %d\n"), request.iAllocationLength); |
380 __PRINT1(_L("length = %d\n"), request.iAllocationLength); |
398 |
381 |
399 TScsiServerRequestSenseResp requestSense; |
382 TScsiServerRequestSenseResp requestSense; |
400 requestSense.iAllocationLength = request.iAllocationLength; |
383 requestSense.iAllocationLength = request.iAllocationLength; |
401 |
384 |
402 requestSense.SetResponseCode(TScsiServerRequestSenseResp::ECurrentErrors); |
385 requestSense.SetResponseCode(TScsiServerRequestSenseResp::ECurrentErrors); |
403 requestSense.iSensePtr = &iSenseInfo; |
386 requestSense.iSensePtr = &iSenseInfo; |
404 requestSense.Encode(iCommandBuf); |
387 requestSense.Encode(iCommandBuf); |
405 |
388 |
406 __PRINT4(_L("Response=0x%x Sense=0x%x, Additional=0x%x, Qualifier=0x%x\n"), |
389 __PRINT4(_L("Response=0x%x Sense=0x%x, Additional=0x%x, Qualifier=0x%x\n"), |
407 iCommandBuf[0], iCommandBuf[02], iCommandBuf[12], iCommandBuf[13]); |
390 iCommandBuf[0], iCommandBuf[02], iCommandBuf[12], iCommandBuf[13]); |
408 |
391 |
409 TPtrC8 writeBuf = iCommandBuf.Left(request.iAllocationLength); |
392 TPtrC8 writeBuf = iCommandBuf.Left(request.iAllocationLength); |
410 iTransport->SetupDataIn(writeBuf); |
393 iTransport->SetupDataIn(writeBuf); |
411 |
394 |
412 // clear the sense info |
395 // clear the sense info |
413 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
396 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
414 return ETrue; |
397 return ETrue; |
415 } |
398 } |
416 |
399 |
417 |
400 |
418 /** |
401 /** |
419 Command Parser for the INQUIRY command (0x12) |
402 Command Parser for the INQUIRY command (0x12) |
420 |
403 |
421 @param aLun Logic unit number |
404 @param aLun Logic unit number |
422 @return ETrue if successful, |
405 @return ETrue if successful, |
423 */ |
406 */ |
424 TBool CScsiServerProtocol::HandleInquiry(const TScsiServerReq& aRequest) |
407 TBool CScsiServerProtocol::HandleInquiry(const TScsiServerReq& aRequest) |
425 { |
408 { |
426 __MSFNLOG |
|
427 const TScsiServerInquiryReq request = static_cast<const TScsiServerInquiryReq&>(aRequest); |
409 const TScsiServerInquiryReq request = static_cast<const TScsiServerInquiryReq&>(aRequest); |
428 |
410 |
429 if (request.iCmdDt || request.iEvpd || request.iPage || iLun >= KUsbMsMaxDrives) |
411 if (request.iCmdDt || request.iEvpd || request.iPage || iLun >= KUsbMsMaxDrives) |
430 { |
412 { |
431 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
413 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
432 return EFalse; |
414 return EFalse; |
433 } |
415 } |
434 |
416 |
435 TScsiServerInquiryResp inquiry(iConfig); |
417 TScsiServerInquiryResp inquiry(iConfig); |
436 |
418 |
437 inquiry.SetAllocationLength(request.iAllocationLength); |
419 inquiry.SetAllocationLength(request.iAllocationLength); |
438 |
420 |
446 |
428 |
447 inquiry.Encode(iCommandBuf); |
429 inquiry.Encode(iCommandBuf); |
448 |
430 |
449 TUint length = inquiry.Length(); |
431 TUint length = inquiry.Length(); |
450 |
432 |
451 TPtrC8 writeBuf = iCommandBuf.Left(length); |
433 TPtrC8 writeBuf = iCommandBuf.Left(length); |
452 iTransport->SetupDataIn(writeBuf); |
434 iTransport->SetupDataIn(writeBuf); |
453 |
435 |
454 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
436 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
455 return ETrue; |
437 return ETrue; |
456 } |
438 } |
457 |
439 |
458 |
440 |
459 /** |
441 /** |
460 Command Parser for the START STOP UNIT command (0x1B) |
442 Command Parser for the START STOP UNIT command (0x1B) |
461 |
443 |
462 @param aData command data (started form position 1) |
444 @param aData command data (started form position 1) |
463 @param aLun Logic unit number |
445 @param aLun Logic unit number |
464 @return ETrue if successful, TFalse otherwise |
446 @return ETrue if successful, TFalse otherwise |
465 */ |
447 */ |
466 TBool CScsiServerProtocol::HandleStartStopUnit(const TScsiServerReq& aRequest) |
448 TBool CScsiServerProtocol::HandleStartStopUnit(const TScsiServerReq& aRequest) |
467 { |
449 { |
468 __MSFNLOG |
450 const TScsiServerStartStopUnitReq request = static_cast<const TScsiServerStartStopUnitReq&>(aRequest); |
469 |
451 |
470 const TScsiServerStartStopUnitReq request = static_cast<const TScsiServerStartStopUnitReq&>(aRequest); |
452 if (request.iLoej) |
471 |
453 { |
472 if (request.iLoej) |
454 if(request.iStart) //Start unit |
473 { |
455 { |
474 if(request.iStart) //Start unit |
456 iDriveManager.Connect(iLun); |
475 { |
457 __PRINT(_L("Load media\n")); |
476 iDriveManager.Connect(iLun); |
|
477 __PRINT(_L("Load media\n")); |
|
478 |
458 |
479 // rd/wr publisher |
459 // rd/wr publisher |
480 iBytesRead[iLun] = 0; |
460 iBytesRead[iLun] = 0; |
481 iBytesWritten[iLun] = 0; |
461 iBytesWritten[iLun] = 0; |
482 |
462 |
483 // publish the initial values |
463 // publish the initial values |
484 iWriteTransferPublisher->DoPublishDataTransferredEvent(); |
464 iWriteTransferPublisher->DoPublishDataTransferredEvent(); |
485 iReadTransferPublisher->DoPublishDataTransferredEvent(); |
465 iReadTransferPublisher->DoPublishDataTransferredEvent(); |
486 } |
466 } |
487 else //Stop unit |
467 else //Stop unit |
488 { |
468 { |
489 iDriveManager.SetCritical(iLun, EFalse); |
469 iDriveManager.SetCritical(iLun, EFalse); |
490 iDriveManager.Disconnect(iLun); |
470 iDriveManager.Disconnect(iLun); |
491 __PRINT(_L("Unload media\n")); |
471 __PRINT(_L("Unload media\n")); |
492 } |
472 } |
493 } |
473 } |
494 |
474 |
495 if (request.iImmed) |
475 if (request.iImmed) |
496 { |
476 { |
497 return ETrue; |
477 return ETrue; |
498 } |
478 } |
499 |
479 |
500 CMassStorageDrive* drive = iDriveManager.Drive(iLun); |
480 CMassStorageDrive* drive = iDriveManager.Drive(iLun); |
501 |
481 |
502 TInt timeLeft (20); // 1 sec timeout |
482 TInt timeLeft (20); // 1 sec timeout |
503 CMassStorageDrive::TMountState mountState; |
483 CMassStorageDrive::TMountState mountState; |
504 |
484 |
505 do |
485 do |
506 { |
486 { |
507 User::After(1000 * 50); // 50 mSec |
487 User::After(1000 * 50); // 50 mSec |
508 --timeLeft; |
488 --timeLeft; |
509 mountState = drive->MountState(); |
489 mountState = drive->MountState(); |
510 |
490 |
511 if ((!request.iStart && mountState != CMassStorageDrive::EConnected) |
491 if ((!request.iStart && mountState != CMassStorageDrive::EConnected) |
512 || |
492 || |
513 (request.iStart && |
493 (request.iStart && |
514 (mountState == CMassStorageDrive::EDisconnecting || |
494 (mountState == CMassStorageDrive::EDisconnecting || |
515 mountState == CMassStorageDrive::EConnected))) |
495 mountState == CMassStorageDrive::EConnected))) |
516 { |
496 { |
517 return ETrue; |
497 return ETrue; |
518 } |
498 } |
519 } while (timeLeft>0); |
499 } while (timeLeft>0); |
520 |
500 |
521 //timeout happend |
501 //timeout happend |
522 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
502 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
523 TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection); |
503 TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection); |
524 return EFalse; |
504 return EFalse; |
525 } |
505 } |
526 |
506 |
527 |
507 |
528 /** |
508 /** |
529 Command Parser for the PREVENT/ALLOW MEDIA REMOVAL command (0x1E) |
509 Command Parser for the PREVENT/ALLOW MEDIA REMOVAL command (0x1E) |
530 |
510 |
531 @param aData command data (started form position 1) |
511 @param aData command data (started form position 1) |
532 @param aLun Logic unit number |
512 @param aLun Logic unit number |
533 @return ETrue if successful. |
513 @return ETrue if successful. |
534 */ |
514 */ |
535 TBool CScsiServerProtocol::HandlePreventMediaRemoval(const TScsiServerReq& aRequest) |
515 TBool CScsiServerProtocol::HandlePreventMediaRemoval(const TScsiServerReq& aRequest) |
536 { |
516 { |
537 __MSFNLOG |
517 const TScsiServerPreventMediaRemovalReq& request = static_cast<const TScsiServerPreventMediaRemovalReq&>(aRequest); |
538 const TScsiServerPreventMediaRemovalReq& request = static_cast<const TScsiServerPreventMediaRemovalReq&>(aRequest); |
518 CMassStorageDrive* drive = GetCheckDrive(); |
539 __FNLOG("CScsiProtocol::HandlePreventMediaRemoval"); |
519 |
540 CMassStorageDrive* drive = GetCheckDrive(); |
520 if (drive == NULL) |
541 |
521 { |
542 if (drive == NULL) |
522 return EFalse; |
543 { |
523 } |
544 return EFalse; |
524 iDriveManager.SetCritical(iLun, request.iPrevent); |
545 } |
525 return ETrue; |
546 iDriveManager.SetCritical(iLun, request.iPrevent); |
526 } |
547 return ETrue; |
|
548 } |
|
549 |
527 |
550 |
528 |
551 /** Cancel active state, Invoked by transnport when it stops */ |
529 /** Cancel active state, Invoked by transnport when it stops */ |
552 TInt CScsiServerProtocol::Cancel() |
530 TInt CScsiServerProtocol::Cancel() |
553 { |
531 { |
554 __MSFNLOG |
532 iDriveManager.SetCritical(CDriveManager::KAllLuns, EFalse); |
555 iDriveManager.SetCritical(CDriveManager::KAllLuns, EFalse); |
533 return KErrNone; |
556 return KErrNone; |
534 } |
557 } |
|
558 |
535 |
559 |
536 |
560 TBool CScsiServerProtocol::HandleReadFormatCapacities(const TScsiServerReq& aRequest) |
537 TBool CScsiServerProtocol::HandleReadFormatCapacities(const TScsiServerReq& aRequest) |
561 /** |
538 /** |
562 * Command Parser for the READ FORMAT CAPACITIES command (0x23) |
539 * Command Parser for the READ FORMAT CAPACITIES command (0x23) |
563 * |
540 * |
564 * @return ETrue if successful, else a standard Symbian OS error code. |
541 * @return ETrue if successful, else a standard Symbian OS error code. |
565 */ |
542 */ |
566 { |
543 { |
567 __MSFNLOG |
544 const TScsiServerReadFormatCapacitiesReq& request = static_cast<const TScsiServerReadFormatCapacitiesReq&>(aRequest); |
568 const TScsiServerReadFormatCapacitiesReq& request = static_cast<const TScsiServerReadFormatCapacitiesReq&>(aRequest); |
|
569 |
545 |
570 CMassStorageDrive* drive = NULL; |
546 CMassStorageDrive* drive = NULL; |
571 for (TInt i = 0; i < 10; i++) |
547 for (TInt i = 0; i < 10; i++) |
572 { |
548 { |
573 drive = GetCheckDrive(); |
549 drive = GetCheckDrive(); |
576 break; |
552 break; |
577 } |
553 } |
578 User::After(100000); |
554 User::After(100000); |
579 } |
555 } |
580 |
556 |
581 if (!drive) |
557 if (!drive) |
582 { |
558 { |
583 return EFalse; |
559 return EFalse; |
584 } |
560 } |
585 |
561 |
586 TUint32 numBlocks = I64LOW(drive->MediaParams().NumBlocks()); |
562 TUint32 numBlocks = I64LOW(drive->MediaParams().NumBlocks()); |
587 |
563 |
588 TScsiServerReadFormatCapacitiesResp response(request.AllocationLength()); |
564 TScsiServerReadFormatCapacitiesResp response(request.AllocationLength()); |
589 response.SetNumberBlocks(numBlocks); |
565 response.SetNumberBlocks(numBlocks); |
590 |
566 |
591 response.Encode(iCommandBuf); |
567 response.Encode(iCommandBuf); |
592 TPtrC8 writeBuf = iCommandBuf; |
568 TPtrC8 writeBuf = iCommandBuf; |
593 iTransport->SetupDataIn(writeBuf); |
569 iTransport->SetupDataIn(writeBuf); |
594 return ETrue; |
570 return ETrue; |
595 } |
571 } |
596 |
572 |
597 |
573 |
598 /** |
574 /** |
599 Command Parser for the READ CAPACITY(10) command (0x25) |
575 Command Parser for the READ CAPACITY(10) command (0x25) |
600 |
576 |
601 @param aData command data (started form position 1) |
577 @param aData command data (started form position 1) |
602 @param aLun Logic unit number |
578 @param aLun Logic unit number |
603 @return ETrue if successful. |
579 @return ETrue if successful. |
604 */ |
580 */ |
605 TBool CScsiServerProtocol::HandleReadCapacity10(const TScsiServerReq& aRequest) |
581 TBool CScsiServerProtocol::HandleReadCapacity10(const TScsiServerReq& aRequest) |
606 { |
582 { |
607 __MSFNLOG |
583 const TScsiServerReadCapacity10Req& request = static_cast<const TScsiServerReadCapacity10Req&>(aRequest); |
608 const TScsiServerReadCapacity10Req& request = static_cast<const TScsiServerReadCapacity10Req&>(aRequest); |
584 CMassStorageDrive* drive = GetCheckDrive(); |
609 CMassStorageDrive* drive = GetCheckDrive(); |
585 if (drive == NULL) |
610 if (drive == NULL) |
586 { |
611 { |
587 return EFalse; |
612 return EFalse; |
588 } |
613 } |
589 |
614 |
590 if (request.iPmi || request.iLogicalBlockAddress) //do not support partial medium indicator |
615 if (request.iPmi || request.iLogicalBlockAddress) //do not support partial medium indicator |
591 { |
616 { |
592 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
617 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
593 return EFalse; |
618 return EFalse; |
594 } |
619 } |
|
620 |
595 |
621 TScsiServerReadCapacity10Resp response; |
596 TScsiServerReadCapacity10Resp response; |
622 response.Set(drive->MediaParams().BlockSize(), drive->MediaParams().NumBlocks()); |
597 response.Set(drive->MediaParams().BlockSize(), drive->MediaParams().NumBlocks()); |
623 response.Encode(iCommandBuf); |
598 response.Encode(iCommandBuf); |
624 |
599 |
625 TPtrC8 writeBuf = iCommandBuf; |
600 TPtrC8 writeBuf = iCommandBuf; |
626 iTransport->SetupDataIn(writeBuf); |
601 iTransport->SetupDataIn(writeBuf); |
627 |
602 |
628 return KErrNone; |
603 return KErrNone; |
629 } |
604 } |
630 |
605 |
631 |
606 |
632 /** |
607 /** |
633 Command Parser for the READ10 command (0x28) |
608 Command Parser for the READ10 command (0x28) |
634 |
609 |
635 @param aData command data (started form position 1) |
610 @param aData command data (started form position 1) |
636 @param aLun Logic unit number |
611 @param aLun Logic unit number |
637 @return ETrue if successful. |
612 @return ETrue if successful. |
638 */ |
613 */ |
639 TBool CScsiServerProtocol::HandleRead10(const TScsiServerReq& aRequest) |
614 TBool CScsiServerProtocol::HandleRead10(const TScsiServerReq& aRequest) |
640 { |
615 { |
641 __MSFNLOG |
616 const TScsiServerRead10Req& request = static_cast<const TScsiServerRead10Req&>(aRequest); |
642 const TScsiServerRead10Req& request = static_cast<const TScsiServerRead10Req&>(aRequest); |
617 CMassStorageDrive* drive = GetCheckDrive(); |
643 CMassStorageDrive* drive = GetCheckDrive(); |
618 if (drive == NULL) |
644 if (drive == NULL) |
619 { |
645 { |
620 return EFalse; |
646 return EFalse; |
621 } |
647 } |
622 |
648 |
623 if (request.iProtect) |
649 if (request.iProtect) |
624 { |
650 { |
625 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
651 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
626 return EFalse; |
652 return EFalse; |
627 } |
653 } |
628 |
654 |
629 if (!request.iTransferLength) |
655 if (!request.iTransferLength) |
630 { |
656 { |
631 return ETrue; // do nothing - this is not an error |
657 return ETrue; // do nothing - this is not an error |
632 } |
658 } |
|
659 |
633 |
660 TUint32 blockSize = drive->MediaParams().BlockSize(); |
634 TUint32 blockSize = drive->MediaParams().BlockSize(); |
661 |
635 |
662 const TInt64 bOffset = static_cast<TInt64>(request.iLogicalBlockAddress) * blockSize; |
636 const TInt64 bOffset = static_cast<TInt64>(request.iLogicalBlockAddress) * blockSize; |
663 const TInt bLength = request.iTransferLength * blockSize; |
637 const TInt bLength = request.iTransferLength * blockSize; |
664 const TInt64 theEnd = bOffset + bLength; |
638 const TInt64 theEnd = bOffset + bLength; |
665 |
639 |
666 if (theEnd > drive->MediaParams().Size()) //check if media big enough for this request |
640 if (theEnd > drive->MediaParams().Size()) //check if media big enough for this request |
667 { |
641 { |
668 __PRINT(_L("err - Request ends out of media\n")); |
642 __PRINT(_L("err - Request ends out of media\n")); |
669 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
643 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
670 return EFalse; |
644 return EFalse; |
671 } |
645 } |
672 |
646 |
673 // check if our buffer can hold requested data |
647 // check if our buffer can hold requested data |
674 if (iDataBuf.MaxLength() < bLength) |
648 if (iDataBuf.MaxLength() < bLength) |
675 { |
649 { |
676 TRAPD(err,iDataBuf.ReAllocL(bLength)); |
650 TRAPD(err,iDataBuf.ReAllocL(bLength)); |
677 if (err) |
651 if (err) |
678 { |
652 { |
679 __PRINT(_L("err - Buffer too small\n")); |
653 __PRINT(_L("err - Buffer too small\n")); |
680 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
654 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
681 return EFalse; |
655 return EFalse; |
682 } |
656 } |
683 } |
657 } |
684 |
658 |
685 iDataBuf.SetLength(bLength); |
659 iDataBuf.SetLength(bLength); |
686 TInt err = drive->Read(bOffset, bLength, iDataBuf); |
660 TInt err = drive->Read(bOffset, bLength, iDataBuf); |
687 if (err != KErrNone) |
661 if (err != KErrNone) |
688 { |
662 { |
689 __PRINT1(_L("Read failed, err=%d\n"), err); |
663 __PRINT1(_L("Read failed, err=%d\n"), err); |
690 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
664 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
691 return EFalse; |
665 return EFalse; |
692 } |
666 } |
693 |
667 |
694 TPtrC8 writeBuf = iDataBuf; |
668 TPtrC8 writeBuf = iDataBuf; |
695 |
669 |
696 // rd publisher |
670 // rd publisher |
697 iBytesRead[iLun] += writeBuf.Length(); |
671 iBytesRead[iLun] += writeBuf.Length(); |
698 iReadTransferPublisher->StartTimer(); |
672 iReadTransferPublisher->StartTimer(); |
699 |
673 |
700 // Set up data write to the host |
674 // Set up data write to the host |
701 #ifdef MSDC_TESTMODE |
675 #ifdef MSDC_TESTMODE |
702 if (iTestParser) |
676 if (iTestParser) |
703 { |
677 { |
704 TBool test = iTestParser->DInSearch(writeBuf); |
678 TBool test = iTestParser->DInSearch(writeBuf); |
705 } |
679 } |
706 #endif |
680 #endif |
707 iTransport->SetupDataIn(writeBuf); |
681 iTransport->SetupDataIn(writeBuf); |
708 return ETrue; |
682 return ETrue; |
709 } |
683 } |
710 |
684 |
711 |
685 |
712 /** |
686 /** |
713 Command Parser for the WRITE(10) command (0x2A) |
687 Command Parser for the WRITE(10) command (0x2A) |
714 |
688 |
715 @param aData command data (started form position 1) |
689 @param aData command data (started form position 1) |
716 @param aLun Logic unit number |
690 @param aLun Logic unit number |
717 @return ETrue if successful. |
691 @return ETrue if successful. |
718 */ |
692 */ |
719 TBool CScsiServerProtocol::HandleWrite10(const TScsiServerReq& aRequest) |
693 TBool CScsiServerProtocol::HandleWrite10(const TScsiServerReq& aRequest) |
720 { |
694 { |
721 __MSFNLOG |
695 const TScsiServerWrite10Req& request = static_cast<const TScsiServerWrite10Req&>(aRequest); |
722 const TScsiServerWrite10Req& request = static_cast<const TScsiServerWrite10Req&>(aRequest); |
696 CMassStorageDrive* drive = GetCheckDrive(); |
723 CMassStorageDrive* drive = GetCheckDrive(); |
697 if (drive == NULL) |
724 if (drive == NULL) |
698 { |
725 { |
699 return EFalse; |
726 return EFalse; |
700 } |
727 } |
701 if (request.iProtect) |
728 if (request.iProtect) |
702 { |
729 { |
703 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
730 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
704 return EFalse; |
731 return EFalse; |
705 } |
732 } |
706 |
733 |
707 if (!request.iTransferLength) |
734 if (!request.iTransferLength) |
708 { |
735 { |
709 return ETrue; // do nothing - this is not an error |
736 return ETrue; // do nothing - this is not an error |
710 } |
737 } |
|
738 |
711 |
739 const TMediaParams& params = drive->MediaParams(); |
712 const TMediaParams& params = drive->MediaParams(); |
740 |
713 |
741 if (params.IsWriteProtected() || |
714 if (params.IsWriteProtected() || |
742 params.IsLocked()) |
715 params.IsLocked()) |
743 { |
716 { |
744 iSenseInfo.SetSense(TSenseInfo::EDataProtection, TSenseInfo::EWriteProtected); |
717 iSenseInfo.SetSense(TSenseInfo::EDataProtection, TSenseInfo::EWriteProtected); |
745 return EFalse; |
718 return EFalse; |
746 } |
719 } |
747 |
720 |
748 TInt64 theEnd = iMediaWriteMan.Start(request.iLogicalBlockAddress, request.iTransferLength, params.BlockSize()); |
721 TInt64 theEnd = iMediaWriteMan.Start(request.iLogicalBlockAddress, request.iTransferLength, params.BlockSize()); |
749 if (theEnd > params.Size()) //check if media big enough for this request |
722 if (theEnd > params.Size()) //check if media big enough for this request |
750 { |
723 { |
751 __PRINT(_L("err - Request ends out of media\n")); |
724 __PRINT(_L("err - Request ends out of media\n")); |
752 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
725 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
753 return EFalse; |
726 return EFalse; |
754 } |
727 } |
755 |
728 |
756 TUint32 thisLength = iMediaWriteMan.GetPacketLength(); |
729 TUint32 thisLength = iMediaWriteMan.GetPacketLength(); |
757 |
730 |
758 // check if our buffer can hold requested data |
731 // check if our buffer can hold requested data |
759 if (iDataBuf.MaxLength() < thisLength) |
732 if (iDataBuf.MaxLength() < thisLength) |
887 err = drive->Write(bOffset, iDataBuf); |
858 err = drive->Write(bOffset, iDataBuf); |
888 } |
859 } |
889 } |
860 } |
890 #else |
861 #else |
891 // ********* Write data to the drive ******** |
862 // ********* Write data to the drive ******** |
892 err = drive->Write(bOffset, iDataBuf); |
863 err = drive->Write(bOffset, iDataBuf); |
893 #endif |
864 #endif |
894 if (err != KErrNone) |
865 if (err != KErrNone) |
895 { |
866 { |
896 __PRINT1(_L("Error after write = 0x%X \n"), err); |
867 __PRINT1(_L("Error after write = 0x%X \n"), err); |
897 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand); |
868 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand); |
898 return KErrAbort; |
869 return KErrAbort; |
899 } |
870 } |
900 |
871 |
901 TUint thisLength = iDataBuf.Length(); |
872 TUint thisLength = iDataBuf.Length(); |
902 aBytesWritten = thisLength; |
873 aBytesWritten = thisLength; |
903 |
874 |
904 iMediaWriteMan.SetOffset(bOffset, thisLength); |
875 iMediaWriteMan.SetOffset(bOffset, thisLength); |
905 |
876 |
906 if (iMediaWriteMan.BytesRemain() == 0) |
877 if (iMediaWriteMan.BytesRemain() == 0) |
907 { |
878 { |
908 return iSenseInfo.SenseOk() ? KErrNone : KErrAbort; |
879 return iSenseInfo.SenseOk() ? KErrNone : KErrAbort; |
909 } |
880 } |
910 |
881 |
911 // More data is expected - set up another request to read from the host |
882 // More data is expected - set up another request to read from the host |
912 const TUint32 nextPacketLength = iMediaWriteMan.NextPacket(); |
883 const TUint32 nextPacketLength = iMediaWriteMan.NextPacket(); |
913 TUint bytesAvail = iTransport->BytesAvailable() & ~(drive->MediaParams().BlockSize()-1); |
884 TUint bytesAvail = iTransport->BytesAvailable() & ~(drive->MediaParams().BlockSize()-1); |
914 |
885 |
915 TBool wait = EFalse; |
886 TBool wait = EFalse; |
916 |
887 |
917 thisLength = nextPacketLength; |
888 thisLength = nextPacketLength; |
918 if (bytesAvail) |
889 if (bytesAvail) |
919 { |
890 { |
920 if (bytesAvail < nextPacketLength) |
891 if (bytesAvail < nextPacketLength) |
925 thisLength = nextPacketLength; |
896 thisLength = nextPacketLength; |
926 wait = ETrue; |
897 wait = ETrue; |
927 } |
898 } |
928 } |
899 } |
929 |
900 |
930 thisLength = (thisLength > KMaxBufSize) ? KMaxBufSize : thisLength; |
901 thisLength = (thisLength > KMaxBufSize) ? KMaxBufSize : thisLength; |
931 |
902 |
932 iDataBuf.SetLength(thisLength); |
903 iDataBuf.SetLength(thisLength); |
933 TPtr8 readBuf = iDataBuf.LeftTPtr(iDataBuf.Length()); |
904 TPtr8 readBuf = iDataBuf.LeftTPtr(iDataBuf.Length()); |
934 iTransport->SetupDataOut(readBuf); |
905 iTransport->SetupDataOut(readBuf); |
935 return wait ? KErrNotReady : KErrCompletion; |
906 return wait ? KErrNotReady : KErrCompletion; |
936 } |
907 } |
937 |
908 |
938 |
909 |
939 /** |
910 /** |
940 Command Parser for the MODE SENSE(06) command (0x1A) |
911 Command Parser for the MODE SENSE(06) command (0x1A) |
941 |
912 |
942 @return ETrue if successful. |
913 @return ETrue if successful. |
943 */ |
914 */ |
944 TBool CScsiServerProtocol::HandleModeSense6(const TScsiServerReq& aRequest) |
915 TBool CScsiServerProtocol::HandleModeSense6(const TScsiServerReq& aRequest) |
945 { |
916 { |
946 __MSFNLOG |
917 const TScsiServerModeSense6Req& request = static_cast<const TScsiServerModeSense6Req&>(aRequest); |
947 const TScsiServerModeSense6Req& request = static_cast<const TScsiServerModeSense6Req&>(aRequest); |
918 |
948 |
919 TScsiServerModeSense6Resp response; |
949 TScsiServerModeSense6Resp response; |
|
950 response.SetAllocationLength(request.iAllocationLength); |
920 response.SetAllocationLength(request.iAllocationLength); |
951 |
921 |
952 if (request.iPageCode != TScsiServerModeSense6Req::KAllPages || |
922 if (request.iPageCode != TScsiServerModeSense6Req::KAllPages || |
953 request.iPageControl == TScsiServerModeSense6Req::EChangeableValues) |
923 request.iPageControl == TScsiServerModeSense6Req::EChangeableValues) |
954 { |
924 { |
955 __PRINT(_L("TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb")); |
925 __PRINT(_L("TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb")); |
956 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb); |
926 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb); |
957 return EFalse; |
927 return EFalse; |
958 } |
928 } |
959 if (request.iPageControl != TScsiServerModeSense6Req::EDefaultValues) |
929 if (request.iPageControl != TScsiServerModeSense6Req::EDefaultValues) |
960 { |
930 { |
961 //check if drive write protected |
931 //check if drive write protected |
962 CMassStorageDrive* drive = GetCheckDrive(); |
932 CMassStorageDrive* drive = GetCheckDrive(); |
963 if (drive == NULL) |
933 if (drive == NULL) |
964 { |
934 { |
965 __PRINT(_L("drive == null")); |
935 __PRINT(_L("drive == null")); |
966 return EFalse; |
936 return EFalse; |
967 } |
937 } |
968 |
938 |
969 #ifdef MSDC_TESTMODE |
939 #ifdef MSDC_TESTMODE |
970 if (iTestParser) |
940 if (iTestParser) |
971 { |
941 { |
972 response.SetWp(iTestParser->WriteProtect()); |
942 response.SetWp(iTestParser->WriteProtect()); |