/* Ċ Ġ* Ġ( C ) ĠCopyright Ġ 2 0 1 4 Ġm j ah nen Ġ< github @ m gn s . tech > Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ* ĠĊ Ġ*/ Ċ Ċ package Ġcom . github . mj dev . lib a ums . driver . scsi Ċ Ċ import Ġandroid . util . Log Ċ import Ġcom . github . mj dev . lib a ums . driver . Block Device Driver Ċ import Ġcom . github . mj dev . lib a ums . driver . scsi . commands .* Ċ import Ġcom . github . mj dev . lib a ums . driver . scsi . commands . Command Block Wrapper . Direction Ċ import Ġcom . github . mj dev . lib a ums . driver . scsi . commands . sense .* Ċ import Ġcom . github . mj dev . lib a ums . usb . Pipe Exception Ċ import Ġcom . github . mj dev . lib a ums . usb . Usb Communication Ċ import Ġjava . io . IOException Ċ import Ġjava . lang . IllegalStateException Ċ import Ġjava . nio . ByteBuffer Ċ import Ġjava . util .* Ċ Ċ /** Ċ Ġ* ĠThis Ġclass Ġis Ġresponsible Ġfor Ġhandling Ġmass Ġstorage Ġdevices Ġwhich Ġfollow Ġthe Ċ Ġ* ĠSC SI Ġstandard . ĠThis Ġclass Ġcommunic ates Ġwith Ġthe Ġmass Ġstorage Ġdevice Ġvia Ġthe Ċ Ġ* Ġdifferent ĠSC SI Ġcommands . Ċ Ġ* Ċ Ġ* Ġ@ author Ġm j ah nen , ĠDer pal us Ċ Ġ* Ġ@ see Ġcom . github . mj dev . lib a ums . driver . scsi . commands Ċ Ġ*/ Ċ class ĠS csi Block Device ( private Ġval Ġusb Communication : ĠU sb Communication , Ġprivate Ġval Ġl un : ĠByte ) Ġ: ĠBlock Device Driver Ġ{ ĊĠĠĠ Ġprivate Ġval Ġout Buffer : ĠByteBuffer Ġ= ĠByteBuffer . allocate ( 3 1 ) ĊĠĠĠ Ġprivate Ġval Ġc sw Buffer : ĠByteBuffer Ġ= ĠByteBuffer . allocate ( Command Status Wrapper . SIZE ) ĊĊĠĠĠ Ġoverride Ġvar ĠblockSize : ĠInt Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġset ĊĠĠĠ Ġprivate Ġvar Ġlast Block Address : ĠInt Ġ= Ġ 0 ĊĊĠĠĠ Ġprivate Ġval Ġwrite Command Ġ= ĠS csi Write 1 0 ( lun = lun ) ĊĠĠĠ Ġprivate Ġval Ġread Command Ġ= ĠS csi Read 1 0 ( lun = lun ) ĊĠĠĠ Ġprivate Ġval Ġc sw Ġ= ĠCommand Status Wrapper () ĊĊĠĠĠ Ġprivate Ġvar Ġcb w Tag Counter Ġ= Ġ 1 ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThe Ġsize Ġof Ġthe Ġblock Ġdevice , Ġin Ġblocks Ġof Ġ[ block Size ] Ġbytes , ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return ĠThe Ġblock Ġdevice Ġsize Ġin Ġblocks ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġval Ġblocks : ĠLong Ġ= Ġlast Block Address . to Long () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIssues Ġa ĠSC SI ĠIn quiry Ġto Ġdetermine Ġthe Ġconnected Ġdevice . ĠAfter Ġthat Ġit Ġis ĊĠĠĠĠ Ġ* Ġchecked Ġif Ġthe Ġunit Ġis Ġready . ĠLogs Ġa Ġwarning Ġif Ġthe Ġunit Ġis Ġnot Ġready . ĊĠĠĠĠ Ġ* ĠFinally Ġthe Ġcapacity Ġof Ġthe Ġmass Ġstorage Ġdevice Ġis Ġread . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ throws ĠIOException ĊĠĠĠĠ Ġ* ĠIf Ġinitial ing Ġfails Ġdue Ġto Ġan Ġunsupported Ġdevice Ġor Ġif ĊĠĠĠĠ Ġ* Ġreading Ġfails . ĊĠĠĠĠ Ġ* Ġ@ see Ġcom . github . mj dev . lib a ums . driver . scsi . commands . S csi In quiry ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ see Ġcom . github . mj dev . lib a ums . driver . scsi . commands . S csi In quiry Response ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ see Ġcom . github . mj dev . lib a ums . driver . scsi . commands . S csi Test Unit Ready ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ see Ġcom . github . mj dev . lib a ums . driver . scsi . commands . S csi Read Capacity ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ see Ġcom . github . mj dev . lib a ums . driver . scsi . commands . S csi Read Capacity Response ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġoverride Ġfun Ġinit () Ġ{ ĊĠĠĠĠĠĠĠ Ġfor ( i Ġin Ġ 0 .. MAX _ RE COVERY _ AT TEMP TS ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinit Attempt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch ( e : ĠInit Required ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġe . message Ġ?: Ġ" Re initial izing Ġdevice ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠNot Ready Try Again ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġe . message Ġ?: Ġ" Re initial izing Ġdevice ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠThread . sleep ( 1 0 0 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġthrow ĠIOException (" MAX _ RE COVERY _ AT TEMP TS ĠEx ceeded Ġwhile Ġtrying Ġto Ġinit Ġcommunication Ġwith ĠUSB Ġdevice , Ġplease Ġre attach Ġdevice Ġand Ġtry Ġagain ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġinit Attempt () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġin Buffer Ġ= ĠByteBuffer . allocate ( 3 6 ) ĊĠĠĠĠĠĠĠ Ġval Ġin quiry Ġ= ĠS csi In quiry ( in Buffer . array (). size . to Byte (), Ġl un = lun ) ĊĠĠĠĠĠĠĠ Ġtransfer Command ( in quiry , Ġin Buffer ) ĊĠĠĠĠĠĠĠ Ġin Buffer . clear () ĊĠĠĠĠĠĠĠ Ġval Ġin quiry Response Ġ= ĠS csi In quiry Response . read ( in Buffer ) ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" in quiry Ġresponse : Ġ$ in quiry Response ") ĊĊĠĠĠĠĠĠĠ Ġif Ġ( in quiry Response . per ipheral Qualifier . toInt () Ġ!= Ġ 0 Ġ|| Ġin quiry Response . per ipheral DeviceType . toInt () Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" unsupported ĠPer ipheral Qualifier Ġor ĠPer ipheral DeviceType ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġtest Unit Ġ= ĠS csi Test Unit Ready ( lun = lun ) ĊĠĠĠĠĠĠĠ Ġtransfer Command Without Data Phase ( test Unit ) ĊĊĠĠĠĠĠĠĠ Ġval Ġread Capacity Ġ= ĠS csi Read Capacity ( lun = lun ) ĊĠĠĠĠĠĠĠ Ġin Buffer . clear () ĊĠĠĠĠĠĠĠ Ġtransfer Command ( read Capacity , Ġin Buffer ) ĊĠĠĠĠĠĠĠ Ġin Buffer . clear () ĊĠĠĠĠĠĠĠ Ġval Ġread Capacity Response Ġ= ĠS csi Read Capacity Response . read ( in Buffer ) ĊĠĠĠĠĠĠĠ ĠblockSize Ġ= Ġread Capacity Response . block Length ĊĠĠĠĠĠĠĠ Ġlast Block Address Ġ= Ġread Capacity Response . logical Block Address ĊĊĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" Block Ġsize : Ġ$ block Size ") ĊĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" Last Ġblock Ġaddress : Ġ$ last Block Address ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠTrans fers Ġthe Ġdesired Ġcommand Ġto Ġthe Ġdevice . ĠIf Ġthe Ġcommand Ġhas Ġa Ġdata ĊĠĠĠĠ Ġ* Ġphase Ġthe Ġparameter Ġ` in Buffer ` Ġis Ġused Ġto Ġstore Ġor Ġread Ġdata ĊĠĠĠĠ Ġ* Ġto Ġresp . Ġfrom Ġit . ĠThe Ġdirection Ġof Ġthe Ġdata Ġphase Ġis Ġdetermined Ġby ĊĠĠĠĠ Ġ* Ġ[# get Direction () ][ com . github . mj dev . lib a ums . driver . scsi . commands . Command Block Wrapper ] ĊĠĠĠĠ Ġ* Ġ. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠReturn Ġvalue Ġis Ġtrue Ġif Ġthe Ġstatus Ġof Ġthe Ġcommand Ġstatus Ġwrapper Ġis ĊĠĠĠĠ Ġ* Ġsuccessful Ġ( ĊĠĠĠĠ Ġ* Ġ[# get b C sw Status () ][ com . github . mj dev . lib a ums . driver . scsi . commands . Command Status Wrapper ] ĊĠĠĠĠ Ġ* Ġ). ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġcommand ĊĠĠĠĠ Ġ* ĠThe Ġcommand Ġwhich Ġshould Ġbe Ġtransferred . ĊĠĠĠĠ Ġ* Ġ@ param Ġin Buffer ĊĠĠĠĠ Ġ* ĠThe Ġbuffer Ġused Ġfor Ġreading Ġor Ġwriting . ĊĠĠĠĠ Ġ* Ġ@ throws ĠIOException ĊĠĠĠĠ Ġ* ĠIf Ġsomething Ġfails . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġtransfer Command ( command : ĠCommand Block Wrapper , Ġin Buffer : ĠByteBuffer ) Ġ{ ĊĠĠĠĠĠĠĠ Ġfor ( i Ġin Ġ 0 .. MAX _ RE COVERY _ AT TEMP TS ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġtransfer One Command ( command , Ġin Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsense Was Not Iss ued Ġ= Ġhandle Command Result ( result ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( sense Was Not Iss ued Ġ|| Ġcommand . direction Ġ== ĠDirection . NONE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġsuccessful Ġw / o Ġneed Ġof Ġsending Ġsense Ġcommand ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOR ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcommand Ġhas Ġno Ġdata Ġphase Ġie . Ġno Ġneed Ġto Ġsent Ġagain ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġand Ġread Ġresponse Ġinto Ġbuffer ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġsense Ġcommand Ġwas Ġsent Ġbecause Ġof Ġerror , Ġsense Ġwas Ġsuccessful ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġie . ĠNO _ S ENSE , ĠRE COVER ED _ ERROR , ĠCOMP LETED , Ġsee ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġsense Ġresponse Ġimpl ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġtry Ġagain Ġand Ġhope Ġthat Ġdata Ġphase Ġie . Ġfilling Ġin Buffer Ġworks Ġnow ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠS ense Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ( e . message Ġ?: Ġ" Sense Exception ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen ( e ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠInit Required Ġ-> Ġinit () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠNot Ready Try Again Ġ-> Ġ{} Ġ// Ġtry Ġagain ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow Ġe ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch ( e : ĠPipe Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ( e . message Ġ?: Ġ" Pipe Exception ") Ġ+ Ġ", Ġtry Ġbulk Ġstorage Ġreset Ġand Ġretry ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbulk Only Mass Storage Reset () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠRetry ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ( e . message Ġ?: Ġ" IOException ") Ġ+ Ġ", Ġretry ing ...") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠThread . sleep ( 1 0 0 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġthrow ĠIOException (" MAX _ RE COVERY _ AT TEMP TS ĠEx ceeded Ġwhile Ġtrying Ġto Ġtransfer Ġcommand Ġto Ġdevice , Ġplease Ġre attach Ġdevice Ġand Ġtry Ġagain ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġtransfer Command Without Data Phase ( command : ĠCommand Block Wrapper ) Ġ{ ĊĠĠĠĠĠĠĠ Ġrequire ( command . direction Ġ== ĠDirection . NONE ) Ġ{ Ġ" Command Ġhas Ġa Ġdata Ġphase " Ġ} ĊĠĠĠĠĠĠĠ Ġtransfer Command ( command , ĠByteBuffer . allocate ( 0 )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġhandle Command Result ( status : ĠInt ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( status ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCommand Status Wrapper . COMMAND _ PAS SED Ġ-> Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCommand Status Wrapper . COMMAND _ FAILED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequest Sense () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCommand Status Wrapper . PHASE _ ERROR Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbulk Only Mass Storage Reset () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" phase Ġerror , Ġplease Ġre attach Ġdevice Ġand Ġtry Ġagain ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠIllegalStateException (" Command Status Ġwrapper Ġillegal Ġstatus Ġ$ status ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġrequest Sense () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġin Buffer Ġ= ĠByteBuffer . allocate ( 1 8 ) ĊĠĠĠĠĠĠĠ Ġval Ġsense Ġ= ĠS csi Request Sense ( in Buffer . array (). size . to Byte (), Ġl un Ġ= Ġl un ) ĊĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġstatus Ġ= Ġtransfer One Command ( sense , Ġin Buffer )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCommand Status Wrapper . COMMAND _ PAS SED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Buffer . clear () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= ĠS csi Request Sense Response . read ( in Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponse . check Response For Error () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCommand Status Wrapper . COMMAND _ FAILED Ġ-> Ġthrow ĠIOException (" request ing Ġsense Ġfailed ") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCommand Status Wrapper . PHASE _ ERROR Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbulk Only Mass Storage Reset () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" phase Ġerror , Ġplease Ġre attach Ġdevice Ġand Ġtry Ġagain ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠIllegalStateException (" Command Status Ġwrapper Ġillegal Ġstatus Ġ$ status ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġbulk Only Mass Storage Reset () Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" sending Ġbulk Ġonly Ġmass Ġstorage Ġrequest ") ĊĠĠĠĠĠĠĠ Ġval Ġb Arr Ġ= ĠByteArray ( 2 ) ĊĠĠĠĠĠĠĠ Ġ// ĠREQUEST _ B UL K _ ONLY _ M ASS _ STORAGE _ RESET Ġ= Ġ 2 5 5 ĊĠĠĠĠĠĠĠ Ġ// ĠREQUEST _ TYPE _ B UL K _ ONLY _ M ASS _ STORAGE _ RESET Ġ= Ġ 3 3 ĊĠĠĠĠĠĠĠ Ġval Ġtransferred : ĠInt Ġ= Ġusb Communication . control Transfer ( 3 3 , Ġ 2 5 5 , Ġ 0 , Ġusb Communication . usb Interface . id , Ġb Arr , Ġ 0 ) ĊĠĠĠĠĠĠĠ Ġif Ġ( transfer red Ġ== Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" bulk Ġonly Ġmass Ġstorage Ġreset Ġfailed !") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Trying Ġto Ġclear Ġhalt Ġon Ġboth Ġendpoints ") ĊĠĠĠĠĠĠĠ Ġusb Communication . clear Feature H alt ( usb Communication . in Endpoint ) ĊĠĠĠĠĠĠĠ Ġusb Communication . clear Feature H alt ( usb Communication . out Endpoint ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġtransfer One Command ( command : ĠCommand Block Wrapper , Ġin Buffer : ĠByteBuffer ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġout Array Ġ= Ġout Buffer . array () ĊĠĠĠĠĠĠĠ ĠArrays . fill ( out Array , Ġ 0 . to Byte ()) ĊĊĠĠĠĠĠĠĠ Ġcommand . d Cb w Tag Ġ= Ġcb w Tag Counter ĊĠĠĠĠĠĠĠ Ġcb w Tag Counter ++ ĊĊĠĠĠĠĠĠĠ Ġout Buffer . clear () ĊĠĠĠĠĠĠĠ Ġcommand . serialize ( out Buffer ) ĊĠĠĠĠĠĠĠ Ġout Buffer . clear () ĊĊĠĠĠĠĠĠĠ Ġvar Ġwritten Ġ= Ġusb Communication . bulk Out Transfer ( out Buffer ) ĊĠĠĠĠĠĠĠ Ġif Ġ( written Ġ!= Ġout Array . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Writing Ġall Ġbytes Ġon Ġcommand Ġ$ command Ġfailed !") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġvar Ġtransfer Length Ġ= Ġcommand . d Cb w Data Transfer Length Ċ // ĠĠĠĠĠĠĠ Ġin Buffer . clear () Ċ // ĠĠĠĠĠĠĠ Ġin Buffer . limit ( transfer Length ) ĊĊĠĠĠĠĠĠĠ Ġvar Ġread Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġif Ġ( transfer Length Ġ> Ġ 0 ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( command . direction Ġ== ĠDirection . IN ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtmp Buffer Ġ= ĠByteBuffer . allocate ( transfer Length ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdo Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġread Ġ+= Ġusb Communication . bulk In Transfer ( in Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġread Ġ+= Ġusb Communication . bulk In Transfer ( tmp Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( command . b Cb w Dynamic Size ) Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransfer Length Ġ= Ġcommand . dynamic Size From Partial Response ( in Buffer ) Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Buffer . limit ( transfer Length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransfer Length Ġ= Ġcommand . dynamic Size From Partial Response ( tmp Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtmp Buffer . limit ( transfer Length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġwhile Ġ( read Ġ< Ġtransfer Length ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( read Ġ!= Ġtransfer Length ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Unexpected Ġcommand Ġsize Ġ(" Ġ+ Ġread Ġ+ Ġ") Ġon Ġresponse Ġto Ġ" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ+ Ġcommand ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtmp Buffer . flip () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Buffer . limit ( in Buffer . position () Ġ+ Ġtransfer Length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġin Buffer . put ( tmp Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwritten Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdo Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwritten Ġ+= Ġusb Communication . bulk Out Transfer ( in Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġwhile Ġ( written Ġ< Ġtransfer Length ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( written Ġ!= Ġtransfer Length ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Could Ġnot Ġwrite Ġall Ġbytes : Ġ$ command ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġ// Ġexpecting Ġc sw Ġnow ĊĠĠĠĠĠĠĠ Ġc sw Buffer . clear () ĊĠĠĠĠĠĠĠ Ġread Ġ= Ġusb Communication . bulk In Transfer ( c sw Buffer ) ĊĠĠĠĠĠĠĠ Ġif Ġ( read Ġ!= ĠCommand Status Wrapper . SIZE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Unexpected Ġcommand Ġsize Ġwhile Ġexpecting Ġc sw ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġc sw Buffer . clear () ĊĊĠĠĠĠĠĠĠ Ġc sw . read ( c sw Buffer ) ĊĠĠĠĠĠĠĠ Ġif Ġ( c sw . d C sw Tag Ġ!= Ġcommand . d Cb w Tag ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" wrong Ġc sw Ġtag !") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġc sw . b C sw Status . toInt () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThis Ġmethod Ġreads Ġfrom Ġthe Ġdevice Ġat Ġthe Ġspecific Ġdevice Ġoffset . ĠThe ĊĠĠĠĠ Ġ* Ġdev Offset Ġspecifies Ġat Ġwhich Ġblock Ġthe Ġreading Ġshould Ġbegin . ĠThat Ġmeans ĊĠĠĠĠ Ġ* Ġthe Ġdev Offset Ġis Ġnot Ġin Ġbytes ! ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġoverride Ġfun Ġread ( device Offset : ĠLong , Ġbuffer : ĠByteBuffer ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// long Ġtime Ġ= ĠSystem . currentTimeMillis (); ĊĠĠĠĠĠĠĠ Ġrequire ( buffer . remaining () Ġ% ĠblockSize Ġ== Ġ 0 ) Ġ{ Ġ" buffer . remaining () Ġmust Ġbe Ġmultiple Ġof ĠblockSize !" Ġ} ĊĊĠĠĠĠĠĠĠ Ġread Command . init ( device Offset . toInt (), Ġbuffer . remaining (), ĠblockSize ) ĊĠĠĠĠĠĠĠ Ġ// Log . d ( TAG , Ġ" reading : Ġ" Ġ+ Ġread ); ĊĊĠĠĠĠĠĠĠ Ġtransfer Command ( read Command , Ġbuffer ) ĊĠĠĠĠĠĠĠ Ġbuffer . position ( buffer . limit ()) ĊĊĠĠĠĠĠĠĠ Ġ// Log . d ( TAG , Ġ" read Ġtime : Ġ" Ġ+ Ġ( System . currentTimeMillis () Ġ- Ġtime )); ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThis Ġmethod Ġwrites Ġfrom Ġthe Ġdevice Ġat Ġthe Ġspecific Ġdevice Ġoffset . ĠThe ĊĠĠĠĠ Ġ* Ġdev Offset Ġspecifies Ġat Ġwhich Ġblock Ġthe Ġwriting Ġshould Ġbegin . ĠThat Ġmeans ĊĠĠĠĠ Ġ* Ġthe Ġdev Offset Ġis Ġnot Ġin Ġbytes ! ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġoverride Ġfun Ġwrite ( device Offset : ĠLong , Ġbuffer : ĠByteBuffer ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// long Ġtime Ġ= ĠSystem . currentTimeMillis (); ĊĠĠĠĠĠĠĠ Ġrequire ( buffer . remaining () Ġ% ĠblockSize Ġ== Ġ 0 ) Ġ{ Ġ" buffer . remaining () Ġmust Ġbe Ġmultiple Ġof ĠblockSize !" Ġ} ĊĊĠĠĠĠĠĠĠ Ġwrite Command . init ( device Offset . toInt (), Ġbuffer . remaining (), ĠblockSize ) ĊĠĠĠĠĠĠĠ Ġ// Log . d ( TAG , Ġ" writing : Ġ" Ġ+ Ġwrite ); ĊĊĠĠĠĠĠĠĠ Ġtransfer Command ( write Command , Ġbuffer ) ĊĠĠĠĠĠĠĠ Ġbuffer . position ( buffer . limit ()) ĊĊĠĠĠĠĠĠĠ Ġ// Log . d ( TAG , Ġ" write Ġtime : Ġ" Ġ+ Ġ( System . currentTimeMillis () Ġ- Ġtime )); ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠMAX _ RE COVERY _ AT TEMP TS Ġ= Ġ 2 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠTAG Ġ= ĠS csi Block Device :: class . java . simple Name ĊĠĠĠ Ġ} Ċ } Ċ