A4 (B8 Platform) Discussion Discussion forum for the B8 Audi A4 produced from 2008.5

Troubleshooting MMI 3G

Thread Tools
 
Search this Thread
 
Old 01-22-2024, 03:43 PM
  #51  
AudiWorld Junior Member
 
mjan's Avatar
 
Join Date: Jan 2024
Posts: 7
Likes: 0
Received 0 Likes on 0 Posts
Default

Originally Posted by sm87
Yeah, it's a classic Java application... I had the same observation regarding DSI, it's the keys to the kingdom of you will, I'm messing in Java to call the StorageAccess interface outside the HMI process (essentially a non violent way to access c and share the /dev/dsi/data file with the HMI process). If you have something like the native pc (persistence client) util mentioned earlier that's definitely a more elegant way to go.
But.. why would you go through so much effort when almost all of the java HMI storage ends up on a sqlite file that can be found and edited at "/mnt/efs-persist/DataPST.db" anyway?
Old 01-22-2024, 06:51 PM
  #52  
AudiWorld Junior Member
Thread Starter
 
sm87's Avatar
 
Join Date: Jan 2014
Posts: 33
Received 2 Likes on 2 Posts
Default

Originally Posted by mjan
But.. why would you go through so much effort when almost all of the java HMI storage ends up on a sqlite file that can be found and edited at "/mnt/efs-persist/DataPST.db" anyway?
@mjan I believe StorageManager also provides access to other "namespaces" including the MMI's EEPROM. There's a possibility to send DSI messages to other car components - all using nothing but an SD card.
I still the intention to try and transplant data from my old MMI's EEPROM to the new unit with this method in order to reset component protection.
Old 01-23-2024, 02:53 AM
  #53  
AudiWorld Junior Member
 
mjan's Avatar
 
Join Date: Jan 2024
Posts: 7
Likes: 0
Received 0 Likes on 0 Posts
Default

Originally Posted by sm87
@mjan I believe StorageManager also provides access to other "namespaces" including the MMI's EEPROM. There's a possibility to send DSI messages to other car components - all using nothing but an SD card.
I still the intention to try and transplant data from my old MMI's EEPROM to the new unit with this method in order to reset component protection.
It does not. The other namespaces are virtual and most of them are read only.
It only has 'access' (if you can call that an access) to certain parts of eeprom via virtual addressing, to read just the required information by HMI.
You can find many of those virtual addresses by going through green menu engineering definition files, this is as far as you're going to access programmatically via DSI.

Regarding the car components - no, you're not talking directly to other car components either.
You're only talking with the native MMI3GApplication, which, very strictly confines what you can and what you cannot do.


If the end goal is to edit eeprom directly by address: Abandon the java part & DSI, this is not going to lead to your goal.

Last edited by mjan; 01-23-2024 at 02:55 AM.
Old 01-23-2024, 08:03 AM
  #54  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

@mjan -- Thanks for that explanation. I suspected that MMI3GApplication is the main application process here, though the means of communicating with other processes (like vdev-logvolmgr and the Java HMI) is not clear to me -- is it a through a device (e.g. /mnt/lvm/comf/console for vdev-logvolmgr), network socket, or shared memory, depending on the other system process ? For example, we see these strings embedded in the MMI3GApplication binary:

Code:
CMUSparePartNumber.cpp
Return PartNumber to PPC :'%s'
MU Spare Part Number in EEPROM %s
Characters in HWKey buffer %c
MU HW Number in EEPROM %s
CMUSparePartNumber deleted!!
PersistencePresCtrl
CMUSparePartNumber created!!
...
CMUSparePartNumberEvent
CFileIO:File close returned %d
CFileIO:File open returned %d
File %s cannot be opened, reason %s
CMUSparePartNumberFileReader.cpp
CMUSparePartNumberFileReader: destructor
CMUSparePartNumberFileReader: constructor
HW Number '%s', Spare Number '%s'
/mnt/efs-extended/tnrref.csv
...
and so on.
Fortunately for me, MMI3GApplication reports the SW_TRAINNAME from the EEPROM to the syslog early in the boot process:

Code:
+++ Train %s
+++ Version MU-MMI3G-%s-%02d.%02d.%04d
Now to tease out the MU h/w part number (and maybe the "EEPROM dataset visible languages"), from the command-line and I'll be happy. --g

Last edited by drgertol; 02-13-2024 at 05:48 AM.
Old 01-23-2024, 08:32 AM
  #55  
AudiWorld Junior Member
Thread Starter
 
sm87's Avatar
 
Join Date: Jan 2014
Posts: 33
Received 2 Likes on 2 Posts
Default

Originally Posted by mjan
It does not. The other namespaces are virtual and most of them are read only.
It only has 'access' (if you can call that an access) to certain parts of eeprom via virtual addressing, to read just the required information by HMI.
You can find many of those virtual addresses by going through green menu engineering definition files, this is as far as you're going to access programmatically via DSI.

Regarding the car components - no, you're not talking directly to other car components either.
You're only talking with the native MMI3GApplication, which, very strictly confines what you can and what you cannot do.


If the end goal is to edit eeprom directly by address: Abandon the java part & DSI, this is not going to lead to your goal.
Ah, well that's disappointing to hear, thanks for confirming though. So the special /dev/dsi/data file is really backed by the MMI3GApplication process then? (I was hoping it might be the other way around, e.g. some kernel driver propping up /dev/dsi/data and applications just reading/writing it as a block device).


Edit:
@drgertol The MMI3GApplication also has these strings:
DSI_MSGCHANNELFILE /dev/dsi/data
DSI_SOCKSRVCONNIP 127.0.0.1
DSI_SOCKSRVCONNPORT (no obvious value)

Like I said, I was hoping this meant MMI3GApplication was reading DSI_MSGCHANNELFILE (just like the java layer), but based on what @mjan says it's the file is a 'service endpoint' hosted by MMI3GApplication.
I bet the "pc" utility you mentioned earlier is using the socket instead.

Last edited by sm87; 01-23-2024 at 08:46 AM.
Old 01-23-2024, 08:47 AM
  #56  
AudiWorld Junior Member
 
mjan's Avatar
 
Join Date: Jan 2024
Posts: 7
Likes: 0
Received 0 Likes on 0 Posts
Default

Originally Posted by sm87
Ah, well that's disappointing to hear, thanks for confirming though. So the special /dev/dsi/data file is really backed by the MMI3GApplication process then? (I was hoping it might be the other way around, e.g. some kernel driver propping up /dev/dsi/data and applications just reading/writing it as a block device).
Yes, it is created and owned by MMI3GApplication.

Talking to the real hardware (other car modules) is very, very hard.
You will find, layer upon layer of different protocols, routing, gateway nuances and the further you go - the more obstacles you are going to find.
Because the very software/hardware was designed in order not to allow something like this to happen.




Last edited by mjan; 01-23-2024 at 08:55 AM.
Old 01-30-2024, 06:49 AM
  #57  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

@sm87 -- On the topic of "troubleshooting MMI3G", can I get your thoughts on a Java-related issue ?

All MMI3G Plus systems with HN+ software have Audi Connect functionality, which was provisioned through the integrated 3G data modem fitted in many main units. This functionality included the ability to import destinations from one's myAudi account on-line. In main units that don't have the integrated data modem or in cases where the 3G modem is not useable (say, for lack of a SIM or data network, as is the case in the U.S. after AT&T shutdown their 3G network in early '22), internet data can be provisioned through a USB/Ethernet interface. When so-called "fair" mode is configured on Plus systems, startup script /mnt/efs-system/lsd/lsd.sh adds /lsd/myaudiconnect_nodataconnection.jar to the BOOTCLASSPATH shell variable, described here: https://www.vwvortex.com/threads/mmi...roken.9520918/
That this does not work as intended has been known for at least 10 years. But I think we have an opportunity to fix this in the myaudiconnect_nodataconnection.jar (or at least understand why this can't work in "fair" mode).

Anyway, I believe this is failing in method processDownloadEvent in MyAudiConnector, from the syslog:

Code:
04:59 LC62DBUG:ListCookieHandler.put: Accepted cookie: JSESSIONID=D28F796F29FF6BABC4E1C8E813CB5EB8.tomcat00
04:59 LC62EROR:LeanSoapTransport.sendReceiveInternal: Caught ioException - transmission incomplete
04:59 LC62EROR:MyAudiConnector.processDownloadEvent: Exception during download of information null
java.io.CharConversionException
at java.io.InputStreamReader.conve...
04:59 LC62WARN:MyAudiConnector: async exception occured (error code: 2002, msg: Connection to myAudi server failed. (null), rtype:0)
...
and the processDownloadEvent method from MyAudiConnector (JAR version):

Code:
  private int processDownloadEvent(StartDownloadEvent startDownloadEvent) {
    int n = 0;
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    int n2 = MyAudiProperties.getInstance().getDataConApplicationID();
    ApplicationConnectionManager.getInstance(MyAudiConnector.this.myLogger, n2).openConnection();
    try {
      if (startDownloadEvent.getType() == 1) {
        MyAudiConnector.access$502(MyAudiConnector.this, this.mySoapClient.downloadAddresses(startDownloadEvent.getKnownIDs(), startDownloadEvent.getDownloadLimit(), true));
      } else if (startDownloadEvent.getType() == 2) {
        MyAudiConnector.access$502(MyAudiConnector.this, this.mySoapClient.downloadAddresses(startDownloadEvent.getKnownIDs(), startDownloadEvent.getDownloadLimit(), false));
      } else {
        MyAudiConnector.this.myLogger.logError("MyAudiConnector.processDownloadEvent: unknown download event");
      }
    }
    catch (IOException iOException) {
      MyAudiConnector.this.myLogger.logError("MyAudiConnector.processDownloadEvent: Exception during download of information " + iOException.getMessage(), iOException);
      if (this.isActive) {
        MyAudiConnector.this.notifyListeners(2002, "Connection to myAudi serverfailed. (" + iOException.getMessage() + ")");
      }
      n = 2002;
    }
    catch (AudiSOAPClientException audiSOAPClientException) {
      MyAudiConnector.this.myLogger.logError("MyAudiConnector.onEvent: " + audiSOAPClientException.getMessage());
      n = audiSOAPClientException.getCorrespondingDSIErrorCode();
    }
    if (this.isActive) {
      ApplicationConnectionManager.getInstance(MyAudiConnector.this.myLogger, n2).closeConnection();
    }
    stopWatch.stop();
    MyAudiConnector.this.myLogger.logDebug("MyAudiConnector.processDownloadEvent: total time for download " + 
 stopWatch.getTimeString());
    return n;
  }
...
and the equivalent method from the LSD.JXE (class g method a):

Code:
  private int a(StartDownloadEvent startDownloadEvent) {
    int n = 0;
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    int n2 = MyAudiProperties.getInstance().getDataConApplicationID();
    ApplicationConnectionManager.getInstance(MyAudiConnector.a(this.d), n2).openConnection();
    try {
      if (startDownloadEvent.getType() == 1) {
        MyAudiConnector.a(this.d, this.a.downloadAddresses(startDownloadEvent.getKnownIDs(), startDownloadEvent.getDownloadLimit(), true));
      } else if (startDownloadEvent.getType() == 2) {
        MyAudiConnector.a(this.d, this.a.downloadAddresses(startDownloadEvent.getKnownIDs(), startDownloadEvent.getDownloadLimit(), false));
      } else {
        MyAudiConnector.a(this.d).logError("MyAudiConnector.processDownloadEvent: unknown download event");
      }
    }
    catch (IOException iOException) {
      MyAudiConnector.a(this.d).logError(((Object)new StringBuffer().append("MyAudiConnector.processDownloadEvent: Exception during download of information ").append(iOException.getMessage())).toString(), iOException);
      if (this.b) {
        MyAudiConnector.a(this.d, 2002, ((Object)new StringBuffer().append("Connection to myAudi server failed. (").append(iOException.getMessage()).append(")")).toString());
      }
      n = 2002;
    }
    catch (AudiSOAPClientException audiSOAPClientException) {
      MyAudiConnector.a(this.d).logError(((Object)new StringBuffer().append("MyAudiConnector.onEvent: ").append(audiSOAPClientException.getMessage())).toString());
      n = audiSOAPClientException.getCorrespondingDSIErrorCode();
    }
    if (this.b) {
      ApplicationConnectionManager.getInstance(MyAudiConnector.a(this.d), n2).closeConnection();
    }
    stopWatch.stop();
    MyAudiConnector.a(this.d).logDebug(((Object)new StringBuffer().append("MyAudiConnector.processDownloadEvent: total time for download ").append(stopWatch.getTimeString())).toString());
    return n;
  }
...
So, any suggestions on what to debug with myLogger messages to syslog (readable by sloginfo) and assuming I can recompile with JDK 1.4 on our Solaris server and repack properly with jar. --g

Last edited by drgertol; 01-30-2024 at 07:54 AM.
Old 01-30-2024, 08:10 AM
  #58  
AudiWorld Junior Member
Thread Starter
 
sm87's Avatar
 
Join Date: Jan 2014
Posts: 33
Received 2 Likes on 2 Posts
Default

Code:
04:59 LC62EROR:MyAudiConnector.processDownloadEvent: Exception during download of information null
java.io.CharConversionException
    at java.io.InputStreamReader.conve...
@drgertol Seems like it's dying while trying to decode the service response, getting a bit more of the stack trace might help.
I noted that lsd.jxe doesn't contain a java.nio.charset.Charset (even though java 1.4 should have it) you have to use methods like String.getBytes(String charsetName). It calls up some IBM-specific implementation behind the scenes where at least some of the charset names are non-standard e.g. "ASCII" instead of "US-ASCII", although "UTF8" seems true to name. It could be related.
I'd look at the implementation of:
MyAudiConnector.access$502(...)
this.mySoapClient.downloadAddresses(...)

If you haven't already, I would try getting the URLs/endpoints that it's trying to call, see what sort of headers (Content-Type, Content-Encoding) it's returning. On top of that, since SOAP is mentioned in method names it could be doing something funny encoding-related in the XML directive <?xml version="1.0" encoding="UTF-8"?>. Also I'm curious what it's using for HTTP/SOAP client, I don't recall seeing anything obvious packed in lsd.jxe.

EDIT: By the way, you don't *have to* build the code on Solaris, Java SE 6 SDK (not any newer) support -sources 1.4 -target 1.4 and that seems to run just fine, as long as you avoid any classes/interfaces missing from lsd.jxe (on Solaris will have the same issue anyway).

Last edited by sm87; 01-30-2024 at 08:13 AM.
Old 01-30-2024, 10:16 AM
  #59  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

@sm87 -- Thanks for that. This has been bugging me since I reworked my mobile data connection to use an LTE router after AT&T turned off 3G data here in Mar '22. I managed to find SDK 1.4 & SE 5 for x64 Solaris at the Oracle archives, so if they work OK, I don't mind using them.

Looks like access$502 is defined locally:
Code:
  static /* synthetic */ PortalADBEntry[] access$502(MyAudiConnector myAudiConnector, PortalADBEntry[] portalADBEntryArray) {
    myAudiConnector.myAddressList = portalADBEntryArray;
    return portalADBEntryArray;
  }
and downloadAddresses comes from class LeanSoapClient:
Code:
  public PortalADBEntry[] downloadAddresses(long[] lArray, int n, boolean bl) throws IOException, AudiSOAPClientException {
    this.myLogger.logDebug("LeanSoapClient.downloadAddresses: Downloading address list");
    DataElementTypeEnum dataElementTypeEnum = bl ? DataElementTypeEnum.ADDRESS_IMPORT : DataElementTypeEnum.ADDRESS_ALL;
    Result result = this.myTransport.getDataElementList(this.myLoginInfo, dataElementTypeEnum, lArray, n);
    if (result == null) {
      this.myLogger.logWarning("LeanSoapClient: received response is null");
      return new PortalADBEntry[0];
    }
    Car2XData car2XData = result.getXmlResult();
    if (car2XData != null && car2XData.getGroup() != null && car2XData.getGroup().length >= 1) {
      if (car2XData.getGroup().length > 1) {
        this.myLogger.logWarning("LeanSoapClient.downloadAddresses: downloadAddresses - received more than one group, only one group expected");
      }
      PortalADBEntry[] portalADBEntryArray = AdbEntryFactory.xmlToAdbEntries(car2XData.getGroup()[0], this.myLogger);
      return portalADBEntryArray;
    }
    return new PortalADBEntry[0];
  }
With that, I think my first experiment will be to inject some myLogger messages in MyAudiConnector.processDownloadEvent to start. --g
Old 01-30-2024, 02:45 PM
  #60  
AudiWorld Member
 
drgertol's Avatar
 
Join Date: Aug 2011
Location: NW OH
Posts: 494
Received 85 Likes on 79 Posts
Default

@sm87 -- What do you make of this. Using j2sdk1.4_30 on Solaris x64, javac returns "wrong version" for a class file extracted from LSD.JXE:
Code:
$ javac14 -classpath .. de/audi/myaudi/impl/MyAudiConnector.java
de/audi/myaudi/impl/MyAudiConnector.java:16: cannot access de.audi.osgi.util.StopWatch
bad class file: ../de/audi/osgi/util/StopWatch.class
class file has wrong version 248.0, should be 48.0
Please remove or make sure it appears in the correct subdirectory of the classpath.
import de.audi.osgi.util.StopWatch;
                         ^
1 error
The class files extracted from myaudiconnect_nodataconnection.jar are in the directory above the (current) source dir, along with required classes from the LSD.JXE. More work to do. --g


Quick Reply: Troubleshooting MMI 3G



All times are GMT -8. The time now is 10:08 AM.