Skip to content

Instantly share code, notes, and snippets.

@mmtrt
Last active April 28, 2024 01:14
Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save mmtrt/5dfbd2559ea988dfbe56277347ac6c96 to your computer and use it in GitHub Desktop.
Save mmtrt/5dfbd2559ea988dfbe56277347ac6c96 to your computer and use it in GitHub Desktop.
[ROOT] [Magisk] [Service.d] [Script] [Fix] DriveDroid on Android 9+
#!/bin/sh
# run while loop for boot_completed status & sleep 10 needed for magisk service.d
while [ "$(getprop sys.boot_completed | tr -d '\r')" != "1" ]; do sleep 1; done
sleep 10
# save currently active function name
echo "$(ls -al /config/usb_gadget/g1/configs/b.1/)" | grep -Eo f1.* | awk '{print $3}' | cut -d/ -f8 > /data/adb/.fixdd
# loop
# run every 0.5 seconds
while true
do
# check the app is active
chkapp="$(pgrep -f drivedroid | wc -l)"
# check currently active function
chkfn=$(echo "$(ls -al /config/usb_gadget/g1/configs/b.1/)" | grep -Eo f1.* | awk '{print $3}' | cut -d/ -f8)
# load previous active function
chkfrstfn="$(cat /data/adb/.fixdd)"
if [ "$chkapp" -eq "1" ] && [ "$chkfn" != "mass_storage.0" ]; then
# add mass_storage.0 config & function and remove currently active function
rm /config/usb_gadget/g1/configs/b.1/f*
mkdir -p /config/usb_gadget/g1/functions/mass_storage.0/lun.0/
ln -s /config/usb_gadget/g1/functions/mass_storage.0 /config/usb_gadget/g1/configs/b.1/f1
elif [ "$chkapp" -eq "0" ] && [ "$chkfn" = "mass_storage.0" ]; then
# remove mass_storage.0 function & restore previous function
rm /config/usb_gadget/g1/configs/b.1/f*
ln -s /config/usb_gadget/g1/functions/"$chkfrstfn" /config/usb_gadget/g1/configs/b.1/f1
if [ "$chkfrstfn" = "ffs.adb" ]; then
setprop sys.usb.config adb
elif [ "$chkfrstfn" = "ffs.mtp" ]; then
setprop sys.usb.config mtp
fi
fi
sleep 0.5
done
@barsikus007
Copy link

I have rewritten this script to support pixel 7 pro. Link to fork.
Could someone review this to be sure?

@mmtrt
Copy link
Author

mmtrt commented Feb 14, 2023

@barsikus007 looks good though we could add check for both functions so it could work with exist change and pixel one if one of each exists.

@mmtrt
Copy link
Author

mmtrt commented Feb 14, 2023

also post output of ls -al /config/usb_gadget/g1/functions/ also this as well with usb connected to PC ls -al /config/usb_gadget/g1/configs/b.1/

@overzero-git
Copy link

overzero-git commented Feb 15, 2023

Hello everyone! I solved my problems with Xiaomi Mi Note 10 lite and created simpe Magisk module for auto-config https://github.com/overzero-git/DriveDroid-fix-Magisk-module

@barsikus007
Copy link

also post output of ls -al /config/usb_gadget/g1/functions/ also this as well with usb connected to PC ls -al /config/usb_gadget/g1/configs/b.1/

ls -al /config/usb_gadget/g1/functions/
total 0
drwxr-xr-x 14 system system 0 2023-02-15 14:36 .
drwxr-xr-x  6 system system 0 2023-02-16 09:53 ..
drwxr-xr-x  2 system system 0 2023-02-15 14:36 accessory.gs2
drwxr-xr-x  2 system system 0 2023-02-15 14:36 acm.gs6
drwxr-xr-x  2 system system 0 2023-02-15 14:36 acm.uwb0
drwxr-xr-x  2 system system 0 2023-02-15 14:36 audio_source.gs3
drwxr-xr-x  2 system system 0 2023-02-15 14:36 dm.gs7
drwxr-xr-x  2 root   root   0 2023-02-15 14:36 etr_miu.gs11
drwxrwx---  2 system system 0 2023-02-15 14:36 ffs.adb
drwxr-xr-x  2 system system 0 2023-02-15 14:36 ffs.mtp
drwxr-xr-x  2 system system 0 2023-02-15 14:36 ffs.ptp
drwxr-xr-x  2 system system 0 2023-02-15 14:36 midi.gs5
drwxr-xr-x  3 system system 0 2023-02-15 14:36 ncm.gs9
drwxr-xr-x  3 system system 0 2023-02-15 14:36 rndis.gs4
ls -al /config/usb_gadget/g1/configs/b.1/
total 0
drwxr-xr-x 3 system system    0 2023-02-16 09:53 .
drwxr-xr-x 3 system system    0 2023-02-15 14:36 ..
-rw-r--r-- 1 system system 4096 2023-02-15 14:36 MaxPower
-rw-r--r-- 1 system system 4096 2023-02-15 14:36 bmAttributes
lrwxrwxrwx 1 root   root      0 2023-02-16 09:53 function0 -> ../../../../usb_gadget/g1/functions/ffs.adb
drwxr-xr-x 2 system system    0 2023-02-15 14:36 strings
# when in charging mode

ls -al /config/usb_gadget/g1/configs/b.1/
total 0
drwxr-xr-x 3 system system    0 2023-02-16 14:44 .
drwxr-xr-x 3 system system    0 2023-02-15 14:36 ..
-rw-r--r-- 1 system system 4096 2023-02-15 14:36 MaxPower
-rw-r--r-- 1 system system 4096 2023-02-15 14:36 bmAttributes
lrwxrwxrwx 1 root   root      0 2023-02-16 14:44 function0 -> ../../../../usb_gadget/g1/functions/ffs.mtp
lrwxrwxrwx 1 root   root      0 2023-02-16 14:44 function1 -> ../../../../usb_gadget/g1/functions/ffs.adb
drwxr-xr-x 2 system system    0 2023-02-15 14:36 strings
# when in MTP mode

@barsikus007
Copy link

btw why are you removing previous functions?
I just added one more function at the folder and this works

ls -al /config/usb_gadget/g1/configs/b.1/
total 0
drwxr-xr-x 3 system system    0 2023-02-16 14:48 .
drwxr-xr-x 3 system system    0 2023-02-15 14:36 ..
-rw-r--r-- 1 system system 4096 2023-02-15 14:36 MaxPower
-rw-r--r-- 1 system system 4096 2023-02-15 14:36 bmAttributes
lrwxrwxrwx 1 root   root      0 2023-02-16 14:48 function0 -> ../../../../usb_gadget/g1/functions/ffs.mtp
lrwxrwxrwx 1 root   root      0 2023-02-16 14:48 function1 -> ../../../../usb_gadget/g1/functions/ffs.adb
drwxr-xr-x 2 system system    0 2023-02-15 14:36 strings

path_to_func="/config/usb_gadget/g1/configs/b.1/function2"
mkdir -p /config/usb_gadget/g1/functions/mass_storage.0/lun.0/
ln -s /config/usb_gadget/g1/functions/mass_storage.0 $path_to_func

ls -al /config/usb_gadget/g1/configs/b.1/
total 0
drwxr-xr-x 3 system system    0 2023-02-16 14:50 .
drwxr-xr-x 3 system system    0 2023-02-15 14:36 ..
-rw-r--r-- 1 system system 4096 2023-02-15 14:36 MaxPower
-rw-r--r-- 1 system system 4096 2023-02-15 14:36 bmAttributes
lrwxrwxrwx 1 root   root      0 2023-02-16 14:48 function0 -> ../../../../usb_gadget/g1/functions/ffs.mtp
lrwxrwxrwx 1 root   root      0 2023-02-16 14:48 function1 -> ../../../../usb_gadget/g1/functions/ffs.adb
lrwxrwxrwx 1 root   root      0 2023-02-16 14:50 function2 -> ../../../../usb_gadget/g1/functions/mass_storage.0
drwxr-xr-x 2 system system    0 2023-02-15 14:36 strings

@barsikus007
Copy link

I impemented function appending, and script is probably should work for both types of function names
How its looks like when you have all modes (adb also available)
both modes works

@knightofdemons
Copy link

knightofdemons commented Feb 22, 2023

just gonna add my 2cents from the recent week aswell, cause this script seems to evolve.

  1. there is a really nice detection function for the usb_gadget folders in the gitrep for the usb-gadget app by tejado.
    see line 64 here for the code: https://github.com/tejado/android-usb-gadget/blob/master/app/src/main/java/net/tjado/usbgadget/GadgetShellApi.kt#L64
    maybe someone can work that in, cause the config-path seems to be different for many devices and versions.
  2. yes, you can just stack the usb-modes. just leave the existing configuration with f1/function1 and create a new f2/function2 and bind the desired usb-mode to this function.
  3. some devices (like mine) need a "reconnect" of the usb-gadget controller once a new mode has been added. tejados usb-gadget-app did this very well too: just clear the usb-gadget controller with echo "" > /config/usb_gadget/g1//UDC then add the modes and reattach it with getprop sys.usb.controller > /config/usb_gadget/g1//UDC because all that stuff is still cached in the sysprop.
  4. here is the official documentation for the android usb-gadget in configfs: https://android.googlesource.com/kernel/msm/+/android-msm-marlin-3.18-nougat-dr1/Documentation/usb/gadget_configfs.txt not very deep but gives a good overview over all options and possibilities.
  5. iam not experienced in programming an app myself but i dont think it should be that hard to just make an successor to drivedroid (or even decompile the code). all it would need is to mount the image-file to the in/outputs of the usb-module. well thats easy to say but according to this comment-section, someone could make a few bucks on the playstore.
  6. use macrodroid to create a macro that will kill the app once its closed. then the script will automatically restore the normal usb-function without force stopping the app every time. most of you probably already figured that out.

@raizr55
Copy link

raizr55 commented Apr 26, 2023

Does it solve this problem?

Screenshot_٢٠٢٣٠٤٢٦-٠٨٠٧١٧

@wojtekojtek
Copy link

Does it solve this problem?

Screenshot_٢٠٢٣٠٤٢٦-٠٨٠٧١٧

Yes. I also had this problem on my sm-a137f. Just install this

Hello everyone! I solved my problems with Xiaomi Mi Note 10 lite and created simpe Magisk module for auto-config https://github.com/overzero-git/DriveDroid-fix-Magisk-module

and make macro

use macrodroid to create a macro that will kill the app once its closed. then the script will automatically restore the normal usb-function without force stopping the app every time. most of you probably already figured that out.

@batasa0986
Copy link

Hi, d
Screenshot_20230813-061734_DriveDroid
oes anyone have any script or fix for driverdroid on my samsung a30?

@Kissycat
Copy link

Kissycat commented Aug 13, 2023

anyone have any script or fix for driverdroid on my samsung a30?

Use it with that script, and remember to replace all 'mass_storage.0' to 'mass_storage.usb0' in that script.

@batasa0986
Copy link

ai có tập lệnh hoặc bản sửa lỗi nào cho driverdroid trên samsung a30 của tôi không?

Sử dụng với lệnh tập tin đó.

Hi can you teach me how to use that script I don't know how to use it, thanks

@Kissycat
Copy link

Hi can you teach me how to use that script I don't know how to use it, thanks

There is a way: Download Termux, then run commands follow one by one.

wget https://gist.github.com/mmtrt/5dfbd2559ea988dfbe56277347ac6c96/raw/478204e0d0107f14ec0af3e0d4b4774e6f598838/fixdd

chmod 0755 ./fixdd

su -c ./fixdd

Open the app.

@batasa0986
Copy link

Xin chào, bạn có thể dạy tôi cách sử dụng tập lệnh đó không. Tôi không biết cách sử dụng nó, cảm ơn

Có một cách: Tải Termux về rồi chạy lệnh lần lượt.

wget https://gist.github.com/mmtrt/5dfbd2559ea988dfbe56277347ac6c96/raw/478204e0d0107f14ec0af3e0d4b4774e6f598838/fixdd

chmod 0755 ./fixdd

su -c ./fixdd

Mở ứng dụng.

Hey, is this fixed yet, can you tell me more, thank you
Screenshot_20230813-184717_Termux

@Kissycat
Copy link

Hey, is this fixed yet

Not yet, bro, there are three commands, you need to exec it line by line..

@batasa0986
Copy link

Này, cái này đã sửa chưa

Chưa đâu bác, có 3 câu lệnh, phải thực hiện từng dòng một..

so can you tell me not to give the full order

@batasa0986
Copy link

Này, cái này đã sửa chưa

Chưa đâu bác, có 3 câu lệnh, phải thực hiện từng dòng một..

Is that wrong or right bro?
Uploading Screenshot_20230813-204153_Termux.jpg…

@batasa0986
Copy link

Sos sos
Samsung a305f

Description:
  DriveDroid cannot find any USB devices

Type of this Android device:
 

Additional information:
 

log:
 

Exception:
  com.softwarebakery.drivedroid.components.support.SubmitReportFailed: Failed to submit report
  at com.softwarebakery.drivedroid.components.support.SupportActivity$onAccept$3.a(SourceFile:148)
  at com.softwarebakery.drivedroid.components.support.SupportActivity$onAccept$3.a(SourceFile:25)
  at rx.internal.util.ActionSubscriber.a(SourceFile:44)
  at rx.observers.SafeSubscriber.b(SourceFile:153)
  at rx.observers.SafeSubscriber.a(SourceFile:115)
  at rx.internal.operators.OperatorSubscribeOn$1$1.a(SourceFile:59)
  at rx.internal.operators.OperatorSubscribeOn$1$1.a(SourceFile:59)
  at rx.observers.Subscribers$5.a(SourceFile:230)
  at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.a(SourceFile:87)
  at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.a(SourceFile:273)
  at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.a(SourceFile:216)
  at rx.internal.schedulers.ScheduledAction.run(SourceFile:55)
  at android.os.Handler.handleCallback(Handler.java:938)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:246)
  at android.app.ActivityThread.main(ActivityThread.java:8653)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
  Caused by: com.softwarebakery.drivedroid.components.downloads.sources.RepositoryHttpException: Failed to retrieve repository: failed to retrieve HTTP response
  at com.softwarebakery.common.rx.RxHttp$enqueue$1$2.onFailure(SourceFile:24)
  at okhttp3.RealCall$AsyncCall.execute(SourceFile:161)
  at okhttp3.internal.NamedRunnable.run(SourceFile:32)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  at java.lang.Thread.run(Thread.java:923)
  Caused by: javax.net.ssl.SSLHandshakeException: Chain validation failed
  at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:362)
  at com.android.org.conscrypt.ConscryptEngine.convertException(ConscryptEngine.java:1134)
  at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1089)
  at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
  at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
  at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
  at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:849)
  at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access$100(ConscryptEngineSocket.java:722)
  at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:238)
  at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:217)
  at okhttp3.internal.connection.RealConnection.connectTls(SourceFile:302)
  at okhttp3.internal.connection.RealConnection.establishProtocol(SourceFile:270)
  at okhttp3.internal.connection.RealConnection.connect(SourceFile:162)
  at okhttp3.internal.connection.StreamAllocation.findConnection(SourceFile:257)
  at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(SourceFile:135)
  at okhttp3.internal.connection.StreamAllocation.newStream(SourceFile:114)
  at okhttp3.internal.connection.ConnectInterceptor.intercept(SourceFile:42)
  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:147)
  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:121)
  at okhttp3.internal.cache.CacheInterceptor.intercept(SourceFile:93)
  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:147)
  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:121)
  at okhttp3.internal.http.BridgeInterceptor.intercept(SourceFile:93)
  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:147)
  at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(SourceFile:126)
  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:147)
  at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:121)
  at okhttp3.RealCall.getResponseWithInterceptorChain(SourceFile:200)
  at okhttp3.RealCall$AsyncCall.execute(SourceFile:147)
  ... 4 more
  Caused by: java.security.cert.CertificateException: Chain validation failed
  at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:724)
  at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:554)
  at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:575)
  at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:620)
  at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:620)
  at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:620)
  at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:510)
  at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:428)
  at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:356)
  at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
  at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:90)
  at com.android.org.conscrypt.ConscryptEngineSocket$2.checkServerTrusted(ConscryptEngineSocket.java:161)
  at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:250)
  at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1644)
  at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(Native Method)
  at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:568)
  at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
  at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
  ... 30 more
  Caused by: java.security.cert.CertPathValidatorException: timestamp check failed
  at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135)
  at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:222)
  at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140)
  at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)
  at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301)
  at android.sec.enterprise.certificate.DelegatingCertPathValidator.engineValidate(DelegatingCertPathValidator.java:63)
  at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301)
  at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:720)
  ... 47 more
  Caused by: java.security.cert.CertificateExpiredException: Certificate expired at Sat Apr 18 19:00:00 GMT+07:00 2020 (compared to Wed Aug 16 14:58:18 GMT+07:00 2023)
  at com.android.org.conscrypt.OpenSSLX509Certificate.checkValidity(OpenSSLX509Certificate.java:269)
  at sun.security.provider.certpath.BasicChecker.verifyTimestamp(BasicChecker.java:194)
  at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:144)
  at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125)
  ... 54 more

 
Screenshot_20230805-181211_DriveDroid

@mmtrt
Copy link
Author

mmtrt commented Aug 16, 2023

@batasa0986

post output of ls -al /config/usb_gadget/g1/functions/ also this as well with usb connected to PC ls -al /config/usb_gadget/g1/configs/b.1/ without using any script.

@liwa-dev
Copy link

IT DOESN'T WORK ANYONE HELP ME PLEASE!!!?

@liwa-dev
Copy link

@mmtrt Windows 10 ISO file gives this error: No device drivers were found. Still this error after choosing CD-ROM option to host

IMG_20221027_171354

IMG_20221027_171628

IMG_20221027_180000

SAME ISSUEE I HAVE

@liwa-dev
Copy link

It doesn't really work when i write this on termux
~ $ su -c "curl -sL https://gist.github.com/mmtrt/5dfbd2559ea988dfbe56277347ac6c96/raw/478204e0d0107f14ec0af3e0d4b4774e6f598838/fixdd > /data/adb/service.d/fixdd && chmod +x /data/adb/service.d/fixdd"
/system/bin/sh: can't create /data/adb/service.d/fixdd: No such file or directory
~ $ su
xdd && chmod +x /data/adb/service.d/fixdd" <
/system/bin/sh: can't create /data/adb/service.d/fixdd: No such file or directory
1|:/data/data/com.termux/files/home #

@rauf4ik123
Copy link

rauf4ik123 commented Oct 3, 2023

Please help me... samsung s20+
Screenshot_20231004_000019_DriveDroid

Screenshot_20231004_001353_Settings

@AliyevYT
Copy link

AliyevYT commented Oct 28, 2023

Not working on Redmi 5 LOS 20 Please help me

@mym4y4
Copy link

mym4y4 commented Nov 15, 2023

overzero-git
Hello everyone! I solved my problems with Xiaomi Mi Note 10 lite and created simpe Magisk module for auto-config https://github.com/overzero-git/DriveDroid-fix-Magisk-module

Confirmed!
Galaxy S9 - Android 13

@Kissycat
Copy link

Oh, guys, stop talking this, just see what you have in your phone's dir /config/usb_gadget/g1/functions, if there is mass_storage.0, then use the script above, and if there is mass_storage.usb0 instead, just do this.

Or you have anything else, just edit the droid apk yourself.

@animegamer4422
Copy link

I got drivedroid working but it cannot really boot any ISO
I tried with Pop os
Below are the attached images

P_20231122_191425

After booting from drivedroid the grub menu appears as expected

P_20231122_191445

But pressing enter doesn't boots the iso instead throws an error saying kernel cannot be found

It could be a mounting issue

@rauf4ik123
Copy link

rauf4ik123 commented Nov 22, 2023 via email

@be4zad
Copy link

be4zad commented Apr 2, 2024

Worked on Samsung A03 Core (crDroid GSI ROM, Android 13)
I booted Archlinux with it :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment