Troubleshooting MMI 3G
#51
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
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.
#52
AudiWorld Junior Member
Thread Starter
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
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.
#53
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
@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.
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 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.
#54
AudiWorld Member
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
@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:
and so on.
Fortunately for me, MMI3GApplication reports the SW_TRAINNAME from the EEPROM to the syslog early in the boot process:
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
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 ...
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
Last edited by drgertol; 02-13-2024 at 05:48 AM.
#55
AudiWorld Junior Member
Thread Starter
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
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.
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.
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.
#56
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
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).
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.
#57
AudiWorld Member
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
@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:
and the processDownloadEvent method from MyAudiConnector (JAR version):
and the equivalent method from the LSD.JXE (class g method a):
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
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) ...
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; } ...
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; } ...
Last edited by drgertol; 01-30-2024 at 07:54 AM.
#58
AudiWorld Junior Member
Thread Starter
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
Code:
04:59 LC62EROR:MyAudiConnector.processDownloadEvent: Exception during download of information null java.io.CharConversionException at java.io.InputStreamReader.conve...
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.
#59
AudiWorld Member
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
@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:
and downloadAddresses comes from class LeanSoapClient:
With that, I think my first experiment will be to inject some myLogger messages in MyAudiConnector.processDownloadEvent to start. --g
Looks like access$502 is defined locally:
Code:
static /* synthetic */ PortalADBEntry[] access$502(MyAudiConnector myAudiConnector, PortalADBEntry[] portalADBEntryArray) { myAudiConnector.myAddressList = portalADBEntryArray; return portalADBEntryArray; }
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]; }
#60
AudiWorld Member
![Default](https://www.audiworld.com/forums/images/icons/icon1.gif)
@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:
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
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