[Q] Android Open Accessory not working on Samsung Galaxy devices? - Other Tools & General Discussion

Hi,
I'm trying to use an Arduino Mega ADK to connect to Android devices using the Android Open Accessory Protocol.
When I connect the Arduino to an Onda tablet using an OTG cable, it detects the Arduino and asks to install the app.
If however, I connect it to a Samsung S3, Galaxy Note II or Galaxy Note 8 nothing happens.
To make sure it wasn't just an issue with the Arduino side, I also implemented it using C# on a .NET MF chip instead of Arduino.
The results are the same, the Onda tablet detects the device, the Samsung devices do not.
Does anybody know if this is a restriction imposed by Samsung for some reason (sounds silly) and is
there a way around it?
Just as a reference, the code I'm using on the Arduino board is just a sample from a wrox book:
Code:
#include <AndroidAccessory.h>
#include <ch9.h>
#include <Max3421e.h>
#include <Max3421e_constants.h>
#include <UsbHost.h>
char application [] = "wrox_temperature_sensor";
char accessory [] = "wrox_temperature_sensor";
char company [] = "Wiley";
char versionNbr[] = "1.0";
char serialNbr[] = "1";
char url[] = "the url to the apk here but I cannot post links in the forum"
int sensorPin = 0;
long timer = millis();
AndroidAccessory usb(company, application, accessory, versionNbr, url,serialNbr);
void setup()
{
usb.begin();
}
void loop()
{
if (usb.isConnected())
{
if( millis() - timer > 10 )
{
int val = analogRead( sensorPin );
float voltage = (val * 5.0) / 1024.0;
float tempCelcius = voltage * 100;
float tempKelvin = tempCelcius + 273.15;
byte * b = (byte *) &tempKelvin;
usb.write(b, 4);
timer = millis();
}
}
}
I should also note the Samsung devices to have a file '/etc/permissions/android.hardware.usb.accessory.xml'
to indicate the device supports Accessory mode:
Code:
<permissions>
<feature name="android.hardware.usb.accessory" />
<library name="com.android.future.usb.accessory"
file="/system/framework/com.android.future.usb.accessory.jar" />
</permissions>
Arduino output when connecting to a Galaxy device:
Device addressed... Requesting device descriptor. found possible
device. swithcing to serial mode could not read device protocol
version
Click to expand...
Click to collapse
Arduino output when connecting to the Onda device:
Device addressed...
Requesting device descriptor. found android
acessory device
config desc interface desc
1
2
Click to expand...
Click to collapse

same behaviour of Galaxy Note 3
I observe a similar behaviour for Samsung Galaxy Note 3 (Android v4.3) when I try to use it with a custom accessory based on an Arduino DUE.
Then GN3 responds to the initial AOA negotiation messages sent by the sketch running on the Arduino but at last it sistematically fails to switch to the accessory mode; Android asks the user to give the permission to launch the App associated to the accessory but, when launched, it works only in write mode (that is The App sends correctly messages to the accessory) but not in read mode (it doesn't receive notifications of available messages from the accessory.
Of course I verified that the same application do it work correctly on other Android devices, also on a Galaxy S2 with Android v4.1.2 (all devices are not rooted).
I am looking for a solution but the debug process is a bit difficult for me.
I Hope someone can give some hint to solve this problem.

Hi every one,
I am working with Android Open Accessory V1.0 with several Samsung devices and it works perfectly ( S3, S2, NOTE 2, etc.)
I have other technical problems with USB communication and especially with ParcelFileDescriptor becoming NULL when restarting the MainActivity
can any one help me with this issue ?

Related

Application crashes when trying to get a list of loaded modules

I have been looking into the C-Sharp__DLLImport project here:
http://forum.xda-developers.com/showthread.php?t=1006331&highlight=dllimport
I am trying to modify the FileSystem project to be able to get a list of the modules that are loaded for each process.
Code:
STDMETHODIMP CFileSystemIO::GetModulesForProcess(DWORD dwPID, BSTR* result)
{
// Get the process snapshot
HANDLE hModuleSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
// Initialize the module entry structure
MODULEENTRY32 moduleEntry = { 0 };
moduleEntry.dwSize = sizeof( moduleEntry );
// Get the first module info
BOOL Return = FALSE;
Return = Module32First( hModuleSnapshot, &moduleEntry);
// Getting process info failed.
if( !Return )
{
CloseHandle( hModuleSnapshot );
return S_FALSE;
}
int x = 1;
CString modList(TEXT(""));
do
{
modList.AppendFormat(TEXT("%d-%d-%d-%d-%d-%d-%s-%s\n"),
moduleEntry.dwSize,
moduleEntry.th32ProcessID,
moduleEntry.GlblcntUsage,
moduleEntry.ProccntUsage,
moduleEntry.modBaseAddr,
moduleEntry.modBaseSize,
moduleEntry.szModule,
moduleEntry.szExePath);
}
while( Module32Next( hModuleSnapshot, &moduleEntry ));
// Close the handle
CloseHandle( hModuleSnapshot );
// set the result
*result = (modList.AllocSysString());
return S_OK;
}
The code is based off a similar function that is already in the project (the CFileSystemIO::MessageBoxRunningProc function which works fine).
By putting some MessageBoxes in there for debugging, I can confirm that the Module32First and Module32Next methods are working correctly. When it gets to the line:
*result = (modList.AllocSysString());
The application crashes. I put a try/catch around there and it didn't trigger a CMemoryException or any other exception.
Any idea why this method would be causing the app to crash?
As an update to this, I was able to figure out the problem. I was unaware of this, but closing the handle generated in the method to get the process messes up the generation of the modules. I didn't think this would be the case since when you generate the handle it also takes a pid. I ended up combining the 2 methods.
The final project uses com interop to call the native methods and it builds a tasklist with all the corresponding modules as subclasses. You can find out which libraries and interfaces are in use by which applications, and where those dll files are located on your phone. If anyone wants to see it, I can post it at some point. It's not a very elegant looking interface, but it gets the job done.

Implementing Google Play Application Silent Install Feature On Android

Hi Experts / Expert Hackers,
I'm trying to implement the Google Play application silent install feature (similar to appbrain fast web installer) on android.
So far I was able achieve the following :
1. Find out a method to retrieve the Google Play Auth Token (thus granting permission for my application to talk with Google Play application on the Phone). I've listed the code I've used for this below :
Code:
Log.i(TAG,"Getting the Google Play Auth Token Using Account Manager : START");
AccountManager accountManager = AccountManager.get(getApplicationContext());
Account[] accArr = accountManager.getAccountsByType("com.google");
for (Account acc : accArr) {
Log.i(TAG, "For Account Name : " + acc.name + " - "+ "Account Type : " + acc.type);
accountManager.getAuthToken(acc, "googleplay", null, this,new AccountManagerCallback<Bundle>() {
public void run(
AccountManagerFuture<Bundle> paramAccountManagerFuture) {
try {
Bundle localBundle = (Bundle) paramAccountManagerFuture.getResult();
String authToken = localBundle.get("authtoken") + "";
Log.i(TAG, "Got AuthToken : " + authToken);
} catch (Exception ex) {
StackTraceElement[] starray = ex.getStackTrace();
StringBuffer bf = new StringBuffer();
bf.append("Error : " + ex.getMessage()).append("\n");
for (StackTraceElement ste : starray) {
bf.append(ste.toString()).append("\n");
}
Log.e(TAG, bf.toString());
}
}
}, null);
}
Log.i(TAG,"Getting the Google Play Auth Token Using Account Manager : END");
2. Find out how to Retrieve the Android-Id of the Phone (This Id as I believe should be used when sending the appInstall request to the GPlay Servers or the Gplay/vending application on the android phone)
Code:
Log.i(TAG, "Getting the Android ID Of the Phone : START");
Uri localUri = Uri.parse("content://com.google.android.gsf.gservices");
ContentResolver localContentResolver = getContentResolver();
String[] arrayOfString = new String[1];
arrayOfString[0] = "android_id";
Cursor localCursor = localContentResolver.query(localUri, null,null, arrayOfString, null);
Log.i(TAG, "Column Count : " + localCursor.getColumnCount());
if ((localCursor != null) && (localCursor.moveToFirst())) {
String androidId = Long.toHexString(Long.parseLong(localCursor.getString(1)));
Log.i(TAG, "Received Android ID : " + androidId);
Log.i(TAG,"Other Value in Column : " + localCursor.getString(0));
}
Log.i(TAG,"Getting the Android ID of the Phone : END");
3. Find out the Protocol Buffer Request to be sent to the Google Play servers or the Gplay/vending application on the phone to Initiate the silent application download & install process.
Code:
message InstallRequest {
optional string appId = 1;
}
message RequestContext {
required string authSubToken = 1;
required bool isSecure = 2;
required int32 version = 3;
required string androidId = 4;
optional string deviceAndSdkVersion = 5;
optional string userLanguage = 6;
optional string userCountry = 7;
optional string operatorAlpha = 8;
optional string simOperatorAlpha = 9;
optional string operatorNumeric = 10;
optional string simOperatorNumeric = 11;
}
message Request {
optional RequestContext context = 1;
repeated group RequestGroup = 2 {
optional InstallRequest installRequest = 10;
}
}
4.I even used the protobuf compiler and generated the java class for manipulating the above protocol buffer request and filled the above protocol buffer fields with some sample data. See the code below :
Code:
public void buildAndSendSilentInstallProtoBuffMessage(String gplayAuthToken, String deviceAndroidId){
try{
/*
* The Root Request Object Assumed to be Holding the Silent Install Request
*/
Request.Builder request = Request.newBuilder();
//Populating the ReequestContext Object
RequestContext.Builder context = RequestContext.newBuilder();
context.setAndroidId(deviceAndroidId);
context.setAuthSubToken(gplayAuthToken);
context.setIsSecure(true);
context.setVersion(1002);
context.setDeviceAndSdkVersion("dream:4");
context.setUserLanguage("en");
context.setUserCountry("us");
context.setOperatorAlpha("Android");
context.setOperatorNumeric("310260");
context.setSimOperatorNumeric("310260");
//Building the Install Request
InstallRequest.Builder installRequest = InstallRequest.newBuilder();
installRequest.setAppId("-2564446724934482383");
//Setting the Install Request to the Request Group
RequestGroup.Builder requestGroup = RequestGroup.newBuilder();
requestGroup.setInstallRequest(installRequest);
//Setting the Request Context to the Main Request Object
request.setContext(context);
//Setting the Request Group to the Request Object
request.addRequestGroup(requestGroup);
The Sample Data for GPlay Token and the Android Id are as follows :
1. Android_ID :
3a0f901831a0f402
2. Google Play AuthToken :
DQAAAMgAAACpOyPf6apRbb0i4qhTVaf0yYoikTAb4TYlHCRLrW4mu5f14j-H35KGmO9TQKUDYCfj3-b-QIH5chfXT3bS02Uxljg7vYt4I-kgXLEJwPcynjugDcJ9fYPOh1c2FnOnywFXXxXw6hcqs5sVnJEt5zW2ditoB5VeeXG9Zfodj9dXKobObi50-XnHoGfWi2b64Uf3EHGdQTsDCMzfZrE4mb22fr9LCW1oZG5tkzwS4KhPBHWMN2fO7w-1IZ4UK5LOI80vPBLjxBaavKAXHoVUHSNV
5. I also did some sniffing using my rooted galaxy nexus phone during Gplay application silent install and found only two HTTP GET Requests.
I tried reproducing the those two Http GET requests captured using Shark for root(using my rooted android galaxy nexus phone) and the 1st Request just downloads the Market File itself (which I was able to save to the SD card of the Phone. But then it has to be installed like any unknown sources application) while the second request returns nothing.
The two get requests captured are shown below :
Code:
1. GET REQUEST ONE :
21 0.827240 192.168.135.102 173.194.36.4 HTTP 535 GET /market/download/Download?packageName=com.gau.go.launcherex.theme.appwidget.gopowermaster.futureworld&versionCode=1&token=AOTCm0QRnH3rmypWtCGoAL_SU1BSt311wpyz-_LZTodkUSAlc-f5SrdMiz5WDRDUKMMm6S3plBI9Jbh1tukT1jyCYXLgP4QhVvZvn5JLtZQ&downloadId=-165214892049282883 HTTP/1.1
Which has the following http headers :
Cookie: MarketDA=17214805622679635526\r\n
Host: android.clients.google.com\r\n
Connection: Keep-Alive\r\n
User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)\r\n
2. GET REQUEST TWO :
44 6.595093 192.168.135.102 222.165.163.15 HTTP 608 GET /market/GetBinary/com.gau.go.launcherex.theme.appwidget.gopowermaster.futureworld/1?expire=1346838270&ipbits=0&ip=0.0.0.0&cp=SnpybWlzSFk6OTYzMzg0MTE2NzA1ODEwOTYxMjE&sparams=expire,ipbits,ip,q:,cp&signature=2C0778C4635F6F8AE1DA8479FB08DCB9BC04C2E9.60202D8D4D2FDDA70609A3862A25852F0BAA2766&key=am2 HTTP/1.1
Which has the following http headers :
Cookie: MarketDA=17214805622679635526\r\n
Host: o-o.preferred.slt-cmb2.v12.lscache4.c.android.clients.google.com\r\n
Connection: Keep-Alive\r\n
User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)\r\n
I've been looking into this for about two weeks now but I still couldn't find the following :
1. Whether the AppBrain fast Web Installer uses the protocol buffer to invoke the Gplay (vending application) on the phone or the Gplay servers ?. If so is the above Protocol Buffer Request format correct ??.
2. If the Above Protocol Buffer Request format is correct then to Where in the Phone or Gplay server should I send the Protocol buffer request to to invoke the Silent Application download and installing procedure ?.
I also have a C2DM (now GCM) server and client setup around this task as well. Could anyone point me in the correct direction or give me any clues for solving this ?. Any help is much appreciated .
Seriously No one ???. I thought this forum has some expert hackers . Where are those so called android hackers anyways ??. Please guys I need help on this and it's urgent .
Hello. How you login into google play with token from account manager? Thanks.

Big Bang steering wheel interface support page

Support Page for the Big Bang Steering Wheel Interface
The purpose of this page is to provide support and answers to questions for the Big Bang Steering Wheel interface until our Wiki and support site at UnderGroundElectronics.net is finished.
We are discussing the Big Bang Steering Wheel interface project on Kickstarter.
A Quick Description: The Big Bang is a interface between the car and your tablet. Our goal is to enable you to install your tablet in your car with OEM like integration. We had to start somewhere and we are planning other items for the future but this critical first step we felt was the most nessasary thing for a every day user experiance.
We know that there are a lot of people and threads on installing tablets in cars. We've seen various methods to achieve this solution but no one has made a item for this specific purpose. Even if your car does not have steering wheel controls, this device allows for the waking and sleeping of the tablet while still allowing it to charge constantly.
This device is fairly simple in operation, however the automobiles they go in are not so simple. There are lot of things that can cause problems and we hope to address them here (until we can get our site up, and maybe even after since XDA is a go to place for trouble shooting problems with our tablets and phones).
Lets Start with a basic description of operation
Most autos that have steering wheel controls use a single wire behind the head unit. This wire is typically one of three types: Resistive Negative, Resistive Positive, and Digital. A few Autos use independent wires, one example is Harley Davison. Each button is independent and thus must use resisters to combine the buttons to a single wire.
Currently the Big Bang is made to work on Negative and positive resistive Autos. Data type is expected to be developed by the time we ship.
Finding the wire in your auto:
At the steering column is the best way. But BE WARNED, there is danger probing around with the electrical system of any car that has airbags. You should disconnect the battery and let the car sit at least 30 minutes before doing anything with the wiring in a car with air bags. (Yes we realize that this is very cautious stand but we don't want people getting hurt. If you are un-experienced with Automotive electrical or unsure of what you are doing you probably should consult you local Car Stereo Shop. At the very least use sites like "the 12volt .com" or ask for assistance here. AND NEVER EVER USE A TEST LIGHT, Voltmeters only here.
We can't stress this enough. The data systems and air bag systems in modern cars are very sensitive and can be damaged or set off with just static electricity. We can not be held responsible for what you are doing, we are simply trying to guide you. In my case I have years of car audio experience. I still run into things in new cars that I've never seen before and I've seen plenty of cars damaged by people cutting the wire that was the right color or "injecting voltage" to test something.
Moving forward:
Negative systems:
Typically a Negative system is one that the control wire will go negative from a resting position that is positive. In the case of most Honda's it rests at 5V and goes negative with each button. If you have a stock navigation system (In the case of the Honda. Others may be different) some buttons may be dedicated to the Nav Brain. That unit needs to be removed with the head unit to function properly and has special "reverse wiring" to provide all buttons functions.
Positive systems
Positive systems work just like negative systems but instead rest at or near ground (zero voltage). The voltage at the wire will go positive when a button is pressed.
Programming the Big Bang
Our site will cover most of this but at present the Big Bang is programmed via a PC. We do hope to one day be able to program it from the tablet, allowing one to tweak the controls after install and to improve installation experience. We will provide more detailed instructions closer to launch day but the short of it is you will download a program, modify it to fit your car/application then run it to program the Big Bang.
Connecting the Big Bang
We recommend using the Big Bang with a USB Hub that is powered. We have found some 12V to 5V dc to dc Converters we will link below as well as the USB hubs we recommend. The Big Bang will connect to the USB hub and the USB hub will plug into the tablet or phone. The big bang will have two wires that need to be connected. The Big Bang is powered from the USB power, so it and the tablet are always receiving power. It will have two wires to be connected. The white wire is the control wire and needs to be attached to the steering wheel control wire. The Red one is the ACC[essory] or IGN[ition] wire and needs to be tapped to it as a reference for the cars voltage. This wire should be fused as there is always a potential for shorting. It may be redundant but we still recommend fusing this wire independent of others, or using the same fuse used for the USB 12v to 5v converter.
Problems we've seen in our testing
First and worst problem I've experienced is cheap USB OTG cables. Some are very finicky about the position the sit in to make contact. It could be that they are old and worn out too. We plan to explain a "best methods" guide but best I can say is get decent quality USB OTG adapters for this use.
The second issue I've seen is random reboots. My n7 experiences these only when I'm using it in the car. I'm running Paranoid Android, and I don't believe it is the issue. I believe it is due to the faulty USB cable described above.
Other then that, we've experienced few issues but we are still in somewhat early testing phase.
I'll update this post with Q and A's as they come in. When asking questions about your installation it would be helpful for you to be as thorough as possible. Let us know if you are an experienced car audio person or not. Also make model and year of car may be important.
Until now this has been our idea for our car, we now open it to you. We can't promises anything but if you have suggestions, tell us. We may include the feature. We are working on other products as well to enable people to install their tablet and have it operate as normal as possible.
Tested Devices:
We've tested it on these devices so far but you can help. Get a USB OTG cable for your tablet, then plug in a USB keyboard or mouse and see if it functions. post your results and we'll add it to the list.
Confirmed working:
N10
N7
Galaxy Note2
Galaxy S3
Know to NOT work:
N4
Post #2
So we have run into a problem with the USB OnTheGo mode and charging. The Big Bang requires the tablet to be in USB OTG to receive control inputs. While in USB OTG mode the tablet is not charging. We have found there is another mode, Rid_a mode. By enabling this Rid_a mode the tablet will do both USB OTG and charge. We have it working on some Samsung's, we now need to figure out the nexus line.
It is possible that this is something coded into the kernel so we are looking into that. Right now the two default options, if we can't work it out, are:
A) A source built kernel with this one thing enabled.
B) a much more complicated setup that would auto switch between host and client mode from the ignition control. This we feel is less desirable based off the fact that if one is driving long distances the tablet could die out.
Post #3
Ok, I know I’m a bad person, I have left you hanging for ages. Well, it was not without feeling bad, and it was not on purpose, I’ve just been busy trying to pay bills.
So I suppose I’ll start with an overview. So our prototype is a DigiSpark. You can get one for like $9.99 or less. They are neat little devices. If your cool you can follow this little how to to use the Atiny85 http://youtu.be/30rPt802n1k, Which is where we were going with our own custom board. You might need to understand a little about voltage, voltage dividers and such. I will try to help, but I can’t climb in your car and measure the voltage or resistance for you so you’ll need to know how to use a DVOM and some pretty basic electronics.
Ok so probably the most common steering wheel interface type is a negative type, but there is other types. So for the standard type, I’ll try to diagram This is pure example.
Code:
(-gnd)----|---/\/\/\/\/\-----(s1)--------|
| 12k R1 |
|---/\/\/\/\/\-----(s2)--------|
| 8k R2 |
|---/\/\/\/\/\----(s3)---------|
| 5k R3 |
|---/\/\/\/\/\----(s4)---------|
| 2.4k R4 |
|---/\/\/\/\/\----(s5)---------|
| 1k R5 |
|---/\/\/\/\/\----(s6)---------|
450 R6 |
|---------/\/\/\/\/\---- (+12v (vcc) )
| 1k Rb
|
\ /
\/
MPU pin ?
So basically the way this works is on the steering wheel side the wire is grounded. In my honda there is actually both wire sides, the positive and negative or common resistor/common Switch sides. Since I pulled all of the stock Nav Electronics out, I had to ground the one side and put the 12v through the other. You can find a lot of this info out from PIE, PAC and peripheral websites (They make steering wheel interfaces and they should have some info in the installation manual PDF on what your car will be).
This may not be new to you, but for others: The Math is
R1+Rb
--------- * V (probably 12v, 14.4v running)
R1*Rb
So for each switch we’ll have a voltage, or more specifically a voltage range. I had a bit of a solution for the range part but for most applications having a range will be acceptable. In my case the range was +(-) 0.5v.
This should give you approximately something like S1= 11v to 12v, S2= 8v to 9v, etc
So the problem is we can only use a 0v to 5v range. So either we must adjust Rb or use another solution, such as an OP Amp to reduce the voltages. However it should be enough to adjust the resistance of Rb.
So we are going to use the A/D input pin of the ATtiny85 (digispark). We’ll convert that to a digital number and then compare it to some reference values. We’ll just consider the MSB Most significant bits and ignore the last few. This gives us some range to tolerate voltage fluctuations due to the cars electrical system.
That basically explains the car interface. We can do all kinds of neat stuff. We have a few useable pins so we can add pins for ACC, or door triggers, etc.
Now we need to consider the USB interface. The Digispark makes this easy. It is built on a board that has a USB interface built in. If you are using the ATtiny85 on a DIY you’ll need to make up a USB cable for this part. We’re going to make the steering wheel control look like a USB keyboard or Audio control to the tablet.
For the USB part I found a neat description on XDA in a reply on a post that inspired the basic workings. Understanding the USB ASCii code is important here. Android uses many standard ones. It’s a complicated code as it is meant to be able to grow and handle all kinds of different possible things.
The Main uses I found were in the Standard keyboard codes and in the Audio control codes.
We use the Digispark hex program that comes in the digispark start up guide, keyboard.h . We pass the code calls to keyboard.h and it does the rest, except we need to add our specific functions to keyboard.h.
We’ll modify keyboard.h and write our sketch and program the Arduino/Digispark/ATtiny85. It will loop through reading the A/D and comparing to the pre-determined reference values. When it matches we’ll output a USB code to do something on the tablet.
This is where the problem came in. Of all things I didn’t expect to have a issue charging while acting as a usb host to, effectively, a keyboard. As of USB standard 1.1 using a certain resistance between the two data pins will put it in different modes. Unfortunately what I found was on some Samsung devices this value put it in a different mode, and yet a mode that gave us USB host, didn’t allow for charging. On the Nexus devices I couldn’t find a way at all, without requiring a different kernel to be installed. This left two main choices. A) charge when the car is off only. Which is unacceptable in my opinion. A long drive would kill even a Nexus7 and then you’re stuck with nothing. B) Require an aftermarket kernel/ROM installed. Well we realized guiding one to remove the deck and do some major work to put a tablet in the dash ment they were serious, it didn’t seem fair to expect them to also root/hack the OS on said device. Sure I suppose we could have made it such but it didn’t fit our goal. There is a third option I just now thought of. One could add a circuit that triggered the Host mode change only when the buttons are pressed. This can be as simple as causing a closed/open connection between data+ and data- . This could cause some missed keystrokes but if planned right, it might be a viable solution.
Sketch Code:
Code:
#include "DigiKeyboard.h"
/*
Basic Steering wheel to Tablet (or any computer) controls. Posted here are the basics from a honda ridgeline '07. The steering wheel wire is Green with red stripe, pin 3
The Brown wire, pin 11, Needs to be connected to ground (the buttons are resisters accross those two). This is only Vol+,Vol-, Mode, Ch+, Ch-. I will search for Back and Talk later.
The Resistance Values read from it was: Rest=9.9k, Mode=3.73k, Ch+= 1.69k, Ch-= 780, Vol+=356.8, Vol-=101.4. Using a 1k pull up to the 5V USB lead seems like a good value and will yeild
a large variance in voltage output. The outputs should be Rest=4.5454v, Mode=3.94v, Ch+=3.146v, Ch-=2.19v, Vol+=1.314v, Vol-=.4603v. These can be converted to a 10bit value and are about
Rest=931.4, Mode=807.4, Ch+=644.6, Ch-=448.8, Vol+=269.26, Vol-=94.3. This variance is more then 100 dec thus to allow a wide tolarance we will drop the last four bits and
test only the four MSB. I.E. if analogRead(0)==11010000 then Ch+. The LSB will need to be striped away due to them not being exactly the same otherwise.
Grey wire, at steering coulumb is the Talk and Back button. It works with The Same brown wire as with the volume. 9.99k at rest, Talk= 2.238K, Back= .64k. Used with a 1K resister, They are
Rest=4.5454v, Talk=3.455v, Back=1.95v.
## DISCOVERY, analogRead is a DEC value and is difficult to convert. was going to read value then roll value right and then compare. This would have given a range:
// audioState = audioState >> 7;
// navState = navState >> 7;
##Delay output can act as a Remote turn on for Amplifire.
*/
/* Rest= 931 = 1110100011 = 0x3A3
// Mode=807 = 1100100111 = 0x327
// Ch+=644 = 1010000100 = 0x284
// Ch-=449 = 0111000001 = 0x1C1
// Vol+=269 = 0100001101 = 0x10D
// Vol-=94 = 0001011110 = 0x5E
//
// Rest= 931 = 1110100011 = 0x3A3
// Talk= 708 = 1011000100 = 0x2C4
// Back= 399.6= 0110010000 = 0x190
*/
//const int audioCtrl = 5; //pin 5, analog Read 0
//const int navCtrl = 2; //pin 2, analog Read 1
const int ledPin = 1;
int audioState = 1023; //B1110100011; //Variable to store button Value
int navState = 1023; //B1110100011; //Variable to store button Value
int twiceSel = 0; //Variable for checking for double press of vol- and of back
int storeState = 0; //Store the current state for double press check.
void setup() {
pinMode(ledPin, OUTPUT); // Turn on onboard LED when button is pressed
// pinMode(audioCtrl, INPUT); //P0 is volume up
// digitalWrite(volUp, HIGH); //set the pull up resister
// pinMode(navCtrl, INPUT); //P2 is Volume down
// digitalWrite(volDown, HIGH); //set the pull up resister
}
void loop() {
DigiKeyboard.update();
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
audioState = analogRead(1); //read value at audio control pin2, write it to audioState for further processing
navState = analogRead(0); //Read the value of navagation Control pin5, write it to navagationState for further processing.
// Rest= 931 = 1110100011 = 0x3A3 = 111
// Mode=807 = 1100100111 = 0x327 = 110 >675 <850
// Ch+=644 = 1010000100 = 0x284 = 101 >550 <675
// Ch-=449 = 0111000001 = 0x1C1 = 011 >300 < 500
// Vol+=269 = 0100001101 = 0x10D = 010 >120 < 300
// Vol-=94 = 0001011110 = 0x5E = 000 >50 <110
//
// Rest= 931 = 1110100011 = 0x3A3 = 111
// Talk= 708 = 1011000100 = 0x2C4 = 101 >650 <750
// Back= 399.6= 0110010000 = 0x190 = 011 >350 <450
// TODO:
//Need debounce, or slowdown, or delay. Currently it cycles too fast.
// Add double press Vol- triggers mute
// Add double press Back triggers Home
//Fix the "/" causing search to display "//
// Use Dpad instead of arrow (probably a function of the Keypad arrows)
if (audioState >675 && audioState < 850 ) { //Mode inbetween 675 and 850
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_ENTER); //tell computer Select
digitalWrite(ledPin,LOW);
delay (200); //200ms Delay
}
else if (audioState >550 && audioState < 675) { //Ch+ >550 < 675
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_ARROW_RIGHT); //tell computer Right Arrow
digitalWrite(ledPin,LOW);
delay (200); //200ms Delay
}
else if (audioState >300 && audioState < 500) { //Ch- >300 < 500
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_ARROW_LEFT); //tell computer Left Arrow
digitalWrite(ledPin,LOW);
delay (200); //200ms Delay
}
else if (audioState >120 && audioState < 300) { //Vol+ >120 <300
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_VOL_UP); //tell computer Volume Up
digitalWrite(ledPin,LOW);
delay (200); //200ms Delay
}
else if (audioState >50 && audioState < 110) { //Vol- >50 < 110
delay (200);
for(int x =0; x < 5; x++) {
audioState = analogRead(1); //read button again
if(audioState >50 && audioState < 110){
digitalWrite(ledPin, HIGH);
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_VOL_DOWN); //tell computer Select
digitalWrite(ledPin,LOW);
//if statement test for 5cycle if button pressed again, if not changes vol- if so mutes
}
else if (navState >675 && navState < 850) { //Talk >650<750
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_SEARCH); //tell computer Select
digitalWrite(ledPin,LOW);
delay (200); //200ms Delay
}
else if (navState >350 && navState < 450) { //Back >350 <450
//if statement test for 5cycle if button pressed again, if not back, if so home
// storeState = 0; //Clear storeage
// twiceSel = 0;
// storeState = navState; // back was pressed, we need to store it's current state.
// navState = 0;
delay (200);
for (int x=0; x < 5; x++){ // Test 5 times
navState = analogRead(0); //Read the value of navagation Control pin5, write it to navagationState for further processing
if (navState >350 && navState < 450) { //Back >350 <450
// twiceSel = 1; //pressed twice
//Something different
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_HOME); //tell computer Select
digitalWrite(ledPin,LOW);
}
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_ESC); //tell computer Select
digitalWrite(ledPin,LOW);
}
}
}
/*
OLD code left for Refrence
buttonState = digitalRead(volUp);
if (buttonState == LOW) {
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_VOL_UP); //tell computer to turn the volume down
}
else{
digitalWrite(ledPin, LOW);
}
buttonState = digitalRead(volDown);
if (buttonState == LOW) {
digitalWrite(ledPin, HIGH);
DigiKeyboard.sendKeyStroke(0); //this is generally not necessary but with some older systems it seems to prevent missing the first character after a delay
DigiKeyboard.sendKeyStroke(KEY_VOL_DOWN); //tell computer to turn the volume down
}
else{
digitalWrite(ledPin, LOW);
}
*/
Keyboard.h Code:
Code:
/*
* Based on Obdev's AVRUSB code and under the same license.
*
* TODO: Make a proper file header. :)
* Modified for Digispark by Digistump
*/
#ifndef __DigiKeyboard_h__
#define __DigiKeyboard_h__
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <string.h>
#include "usbdrv.h"
// TODO: Work around Arduino 12 issues better.
//#include <WConstants.h>
//#undef int()
typedef uint8_t byte;
#define BUFFER_SIZE 2 // Minimum of 2: 1 for modifiers + 1 for keystroke
static uchar idleRate; // in 4 ms units
/* We use a simplifed keyboard report descriptor which does not support the
* boot protocol. We don't allow setting status LEDs and but we do allow
* simultaneous key presses.
* The report descriptor has been created with usb.org's "HID Descriptor Tool"
* which can be downloaded from http://www.usb.org/developers/hidpage/.
* Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted
* for the second INPUT item.
*/
PROGMEM char usbHidReportDescriptor[39] = { //USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
0x05, 0x01, // 0x05, 0x01 USAGE_PAGE (Generic Desktop)
0x09, 0x01, // 0x09, 0x06 USAGE (Keyboard)
0xa1, 0x01, // 0xa1, 0x01 COLLECTION (Application)
0x25, 0x01,
0x15, 0x00,
0x75, 0x01,
0x95, 0x05, // REPORT_COUNT (5)
0x09, 0xb5, // USAGE (Scan Next Track)
0x09, 0xb6, // USAGE (Scan Previous Track)
0x09, 0xb7, // USAGE (Stop)
0x09, 0xcd, // USAGE (Play/Pause)
0x09, 0xe2, // USAGE (Mute)
0x81, 0x06, // INPUT (Data,Var,Rel) - relative inputs
// -------------------- volume up/down bits
0x95, 0x02, // REPORT_COUNT (2)
0x09, 0xe9, // USAGE (Volume Up)
0x09, 0xea, // USAGE (Volume Down)
0x81, 0x02, // INPUT (Data,Var,Abs) - absolute inputs
// -------------------- padding bit
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x01, // INPUT (Cnst,Ary,Abs)
//0x05, 0x07, // 0x05, 0x07 USAGE_PAGE (Keyboard) change to 0x0c for consumer device.
//0x19, 0xe0, // 0x19, 0xe0 USAGE_MINIMUM (Keyboard LeftControl)
//0x29, 0xe7, // 0x29, 0xe7 USAGE_MAXIMUM (Keyboard Right GUI)
//0x15, 0x00, // 0x15, 0x00 LOGICAL_MINIMUM (0)
//0x25, 0x01, // 0x25, 0x01 LOGICAL_MAXIMUM (1)
//0x75, 0x01, // 0x75, 0x01 REPORT_SIZE (1)
//0x95, 0x08, // 0x95, 0x08 REPORT_COUNT (8)
//0x81, 0x02, // 0x81, 0x02 INPUT (Data,Var,Abs)
//0x95, 0x01, // 0x95, 0x01 REPORT_COUNT (simultaneous keystrokes)
//0x75, 0x08, // 0x75, 0x08 REPORT_SIZE (8)
//0x25, 0xE7, // 0x25, 0xE7 LOGICAL_MAXIMUM (130) 0x65 originally
//0x19, 0x00, // 0x19, 0x00 USAGE_MINIMUM (Reserved (no event indicated))
//0x29, 0xE7, // 0x29, 0xE7 USAGE_MAXIMUM (Keyboard Application) 0x65 originally
//0x81, 0x00, // 0x81, 0x00 INPUT (Data,Ary,Abs)
0xc0 // 0xc0 END_COLLECTION
};
/* Keyboard usage values, see usb.org's HID-usage-tables document, chapter
* 10 Keyboard/Keypad Page for more codes.
*/
/*
#define MOD_CONTROL_LEFT (1<<0)
#define MOD_SHIFT_LEFT (1<<1)
#define MOD_ALT_LEFT (1<<2)
#define MOD_GUI_LEFT (1<<3)
#define MOD_CONTROL_RIGHT (1<<4)
#define MOD_SHIFT_RIGHT (1<<5)
#define MOD_ALT_RIGHT (1<<6)
#define MOD_GUI_RIGHT (1<<7)
//#define KEY_ARROW_UP 0x52 //Added 2-5-2013 JWA
//#define KEY_ARROW_DOWN 0x51 //Added 2-5-2013 JWA
*/
//Tested with Logitech keyboard on N7. Right Meta key (MOD_GUI_RIGHT) plus F1 = home. Right Meta plus F3= search. Home = Internet home, Search = Windows search Application specific according to Logitech page.
#define KEY_HOME 157 //Added 2-7-2013 JWA according to android doc 3, According to other doc 165
#define KEY_MUTE 0xE9 //Added 2-7-2013 JWA keypad 3 and Page down according to android doc 91/127
#define KEY_SEARCH 127 //Added 2-6-2013 JWA according to android doc 84
#define KEY_ESC 41 //Added 2-6-2013 JWA KEboard ID ESC = 41
// /system/usr/keylayout/geniric.kl
// 172=Home
// 217= Search - 127
// 213== Music
// 140== Calculator
// 158 = Back - 1
// 102=power Confirmed hid usage ID
// 101=menu confirmed
#define KEY_ARROW_LEFT 0x50 // Android dock d-pad left = 105
#define KEY_ARROW_RIGHT 0x4F //Added 2-5-2013 JWA Andorid dock D-pad right=106
#define KEY_ENTER 40 //mode long press could do recent apps key 187
#define KEY_VOL_UP 128 //Added 2-5-2013 JWA 0x80 Andoid dock volume up=115 vdown= 114
#define KEY_VOL_DOWN 129//Added 2-5-2013 JWA 0x81
class DigiKeyboardDevice {
public:
DigiKeyboardDevice () {
TIMSK &= !(1<TOIE0);
cli();
usbDeviceDisconnect();
_delay_ms(250);
usbDeviceConnect();
usbInit();
sei();
// TODO: Remove the next two lines once we fix
// missing first keystroke bug properly.
memset(reportBuffer, 0, sizeof(reportBuffer));
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
}
void update() {
usbPoll();
}
void sendKeyStroke(byte keyStroke) {
sendKeyStroke(keyStroke, 0);
}
void sendKeyStroke(byte keyStroke, byte modifiers) {
while (!usbInterruptIsReady()) {
// Note: We wait until we can send keystroke
// so we know the previous keystroke was
// sent.
usbPoll();
_delay_ms(5);
}
memset(reportBuffer, 0, sizeof(reportBuffer));
reportBuffer[0] = modifiers;
reportBuffer[1] = keyStroke;
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
while (!usbInterruptIsReady()) {
// Note: We wait until we can send keystroke
// so we know the previous keystroke was
// sent.
usbPoll();
_delay_ms(5);
}
// This stops endlessly repeating keystrokes:
memset(reportBuffer, 0, sizeof(reportBuffer));
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
}
//private: TODO: Make friend?
uchar reportBuffer[2]; // buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
};
DigiKeyboardDevice DigiKeyboard = DigiKeyboardDevice();
#ifdef __cplusplus
extern "C"{
#endif
// USB_PUBLIC uchar usbFunctionSetup
uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (usbRequest_t *)((void *)data);
usbMsgPtr = DigiKeyboard.reportBuffer; //
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){
/* class request type */
if(rq->bRequest == USBRQ_HID_GET_REPORT){
/* wValue: ReportType (highbyte), ReportID (lowbyte) */
/* we only have one report type, so don't look at wValue */
// TODO: Ensure it's okay not to return anything here?
return 0;
}else if(rq->bRequest == USBRQ_HID_GET_IDLE){
// usbMsgPtr = &idleRate;
// return 1;
return 0;
}else if(rq->bRequest == USBRQ_HID_SET_IDLE){
idleRate = rq->wValue.bytes[1];
}
}else{
/* no vendor specific requests implemented */
}
return 0;
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __DigiKeyboard_h__
I had planned and some idea of how to implement things like double press vs long press vs single short press all without lots of delay. It had to do with using changes in the AD values to trigger events and use timers to allow other things to happen in the meantime. Also things such as two buttons pressed at the same time could potentially trigger an event.
Unfortunately I’ve abandoned this whole thing. Firstly I have a background in Car audio, so unlike many of you, I am used to a gaping hole in my dash. My stereo is in a state of flux while I come up with exactly what I want to do. Right now I enjoy just popping my Note2 on the dash and using it for my nav/music needs it allows me to keep my tablet in the house. I’m not saying the idea isn’t still great, nor that I don’t love it. If I was in Car Audio still, I would be using Nexus7’s in place of Alpine car stereos all day long.
Links:
http://www.Digistump.com buy your digispark here, Also the source of much of the code, software and info for making things work.
http://www.arduino.cc/ you’ll need the software, bare minimum. The Digispark page may walk you through installing it.
http://www.atmel.com/Images/Atmel-2...ller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf The chip used in this project is based on the ATtiny85. One can use an Arduino if they choose.
https://github.com/digistump/Digisp...er/libraries/DigisparkKeyboard/DigiKeyboard.h Bluebie’s Keyboard.h library.
https://github.com/Bluebie/micronucleus-t85 Bluebie’s bootloader which provides the USB funcitonality
http://www.obdev.at/products/vusb/index.html More info on using an AVR as a USB device
http://www.microchip.com/forums/m618147.aspx Use of a PIC microchip as a USB device
http://www.microchip.com/forums/m440956-print.aspx HID Audio Controler Usage table
http://www.freebsddiary.org/APC/usb_hid_usages.php USB Useage tables.
http://www.usb.org/developers/devclass_docs/Hut1_11.pdf More USB useage tables
http://forum.xda-developers.com/showthread.php?p=36930621 Tunner app for USB FM radio
https://droidperception.wordpress.com/2013/01/13/nexus-7-webcam-attached-update/ Info on using Extrernal USB Webcams
http://forum.xda-developers.com/showthread.php?t=2113259 A great thread on what can be done with a tablet in the car. He beat me to the install by just a month or two. He also was the reason I realized the limitation on the Charging while acting as a host.
Much of the code above is not my work. I made changes to it where I needed to but, specifically in the keybaord.h almost all of it is not mine. Credit goes to Bluebie and/or Digispark for the original work. If they would like me to remove the code, Please ask, I will. However since it's posted on Github I believe it's safe to post here.
I'm working on a way to adapted steering wheel controls on my mustang. But the issue is I have a base with no controls. I want swap out a premuim steering wheel to get this, but I have to have fords flash the acm for it to work. The issue is I still wont have controls for the tablet since mt car does not have bluetooth. So it will become costly. My solution is to use arduino or some other way to communicate with the factory HU. So im looking forward to this as a viable option.
Just an FYI, CM10-based kernel allows USB OTG and charging at the same time.
I've been on this hunt for a couple months now, albeit not hardcore. I have a rooted Galaxy Tab 2 7.0 that I'll be installing into an Infiniti G35. I would be more than happy to test stuff out for you if you want another guinea pig.
Pics to come
I'll post some pics from my installation so you can get an idea of what I did. Hopefully that and the code, etc will help you figure out how to do yours.
So hopefully Posting this will help some people get their own going. Here are the photos from the unit in my car.
My car has two sets of controls, first is the volume and channel buttons, second is the talk and navigate buttons. Also because I removed the complete Nav system the whole circuit was open. This gave me more options on how to do it, but I wen't with the more conventional. The Orange wire is going to ground. The Red and Yellow are each set of controls. The 1K resistors is a pull up resistor sourced from Vin on the digispark.
Hey joeavery2
thanks a lot for the hard work
If I am understanding the connections correctly, the tablet will draw the charge power from the USB Hub correct? If this is the case, is the tablet limited to 500mA charge current?
Hi guys i would ask your help. I have an Alfa Romeo Giulietta, Installed in the dash a nexus 7 2013 and I want use the steering wheel buttons. The car use the protocol is 15765-4 29bit and I have on Bluetooth obd reader. Can you please help me out? Thanks in advance.
Inviato dal mio FRD-L09 utilizzando Tapatalk

[Q] GT-I930x: State of HDMI/MHL implementation for AOSP based ROMs

Hi folks,
i did a little research these days and tried to sort out,
what in fact is missing to make HDMI/MHL work in AOSP based ROMs for the S3 series.
It is really hard to find some useful stuff about it.
All i noticed were some ancient posts about attaching MHL cable causing reboots.
Everyone keeps repeating MHL will not work on AOSP.
I know that HDMI/MHL is weird stuff and reference manual for MHL transceiver SII9244 is not available.
On the other hand this chip is only working as a phy and should be set up correctly at kernel level.
I also know that there'd been many attempts to make it work but i am to dumb to find some reference to tech talks about it.
So it really seems that most parts are implemented and ready to be put together.
At least that's the way it seems to me... and might be bit noobish of course.
Anyway i found something, which might be another key to solve this issue.
Some snippets from the sources at kernel level.
mach-midas.c:
Code:
#ifdef CONFIG_SAMSUNG_MHL
/* I2C15 */
static struct i2c_gpio_platform_data gpio_i2c_data15 = {
.sda_pin = GPIO_MHL_SDA_1_8V, /* GPB2, I2C5_SDA */
.scl_pin = GPIO_MHL_SCL_1_8V, /* GPB3, I2C5_SCL */
.udelay = 3,
.timeout = 0,
};
struct platform_device s3c_device_i2c15 = {
.name = "i2c-gpio",
.id = 15,
.dev = {
.platform_data = &gpio_i2c_data15,
}
};
static struct i2c_board_info i2c_devs15_emul[] __initdata = {
};
/* I2C16 */
#if !defined(CONFIG_MACH_T0) && !defined(CONFIG_MACH_M3) \
&& !defined(CONFIG_MACH_GD2)
static struct i2c_gpio_platform_data gpio_i2c_data16 = {
.sda_pin = GPIO_MHL_DSDA_2_8V,
.scl_pin = GPIO_MHL_DSCL_2_8V,
};
struct platform_device s3c_device_i2c16 = {
.name = "i2c-gpio",
.id = 16,
.dev.platform_data = &gpio_i2c_data16,
};
#endif /* !defined(CONFIG_MACH_T0) */
static struct i2c_board_info i2c_devs16_emul[] __initdata = {
};
#endif
midas-mhl.c:
Code:
static int __init midas_mhl_init(void)
{
int ret;
#define I2C_BUS_ID_MHL 15
ret = i2c_add_devices(I2C_BUS_ID_MHL, i2c_devs_sii9234,
ARRAY_SIZE(i2c_devs_sii9234));
if (ret < 0) {
printk(KERN_ERR "[MHL] adding i2c fail - nodevice\n");
return -ENODEV;
}
#if defined(CONFIG_MACH_T0_EUR_OPEN) || defined(CONFIG_MACH_T0_CHN_OPEN)
sii9234_pdata.ddc_i2c_num = 6;
#elif defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_SP7160LTE) || defined(CONFIG_MACH_T0) \
|| defined(CONFIG_MACH_KONA) || defined(CONFIG_MACH_TAB3) || \
defined(CONFIG_MACH_GD2) || defined(CONFIG_MACH_GC2PD)
sii9234_pdata.ddc_i2c_num = 5;
#else
sii9234_pdata.ddc_i2c_num = (system_rev == 3 ? 16 : 5);
#endif
#ifdef CONFIG_MACH_SLP_PQ_LTE
sii9234_pdata.ddc_i2c_num = 16;
#endif
ret = i2c_add_devices(sii9234_pdata.ddc_i2c_num, &i2c_dev_hdmi_ddc, 1);
if (ret < 0) {
printk(KERN_ERR "[MHL] adding ddc fail - nodevice\n");
return -ENODEV;
}
return 0;
}
This could be found in the AOSP source trees of the Android hal:
https://github.com/omnirom/android_...ynos4/hal/libhdmi/libsForhdmi/libddc/libddc.c
Code:
/**
* @brief DDC device name.
* User should change this.
*/
#ifdef DDC_CH_I2C_1
#define DEV_NAME "/dev/i2c-1"
#endif
#ifdef DDC_CH_I2C_2
#define DEV_NAME "/dev/i2c-2"
#endif
#ifdef DDC_CH_I2C_7
#define DEV_NAME "/dev/i2c-7"
#endif
So i really wonder if someone ever tried to add device "i2c-15" here and compile.
See the implementation for odroid-u3 here as well (which is the base for NamelessROM):
https://github.com/codewalkerster/android_hardware_samsung_slsi_exynos4
Additionally this should be added to the S3 BoardConfig.mk then:
Code:
BOARD_USES_HDMI_SUBTITLES := true
BOARD_USES_HDMI := true
BOARD_HDMI_STD := STD_720P
BOARD_HDMI_DDC_CH := DDC_CH_I2C_15
BOARD_USES_FIMGAPI := true
Please leave some comments and help me to understand what in fact is missing to watch TV with AOSP ROMs :angel:
Regards,
scholbert
That'd be awesome thing having HDMI/MHL out in AOSP. That's the main reason why I'm using stock rom. @codeworkx is the guy you need to talk to but he's no longer in the cyanogenmod team.
Hi [email protected],
thanks for your reply!
I'll try to contact codeworkx, though it seems he had not only left CM team but XDA-devs as well.
[email protected] said:
That'd be awesome thing having HDMI/MHL out in AOSP. That's the main reason why I'm using stock rom. @codeworkx is the guy you need to talk to but he's no longer in the cyanogenmod team.
Click to expand...
Click to collapse
Anyway, i know that there are many parts of code involved to make the MHL interface work, so the main part for me is to know about the missing link.
I guess i'll try to get a better understanding about the kernel side the next days, as there are:
- do we have all parts to map the virtual I2C port for SII9244
- does the initialization of the SII9244 look complete
- what's the state of the HPD GPIO
Next would be of course, to understand how the interaction of framebuffer mapping takes place.
There's the GPU MALI stuff which uses parts of RAM and some framebuffer as well
The internal HDMI logic of Exynos needs some mapping of course to get access to this memory.
This could be the most complex part and maybe this information is missing or done by proprietary stuff...
Let's see if we could get more detailed information about it in the next weeks.
So please help out with useful comments
Best regards,
scholbert
You can find him in the BBQlinux IRC channel. He's the developer of that distro.
Hi there,
again thanks for the reply so far.
I did some further research on this issue on my own....
- Yes, there are proprietary files which handle HDMI (TVOUT) in stock ROMs
- Yes, these libs and services do not seem to match the AOSP implementation
After some investigation on the proprietary files and searching for some ASCII snippets in the binaries, it seems that at least some parts, or better call it functionality, is covered in the HAL present in the AOSP source tree, which had been released for the SMDK4412.
My guessing is that the "framework" is little different in these sources and some of the libraries of the AOSP version have other names, if we manage to compile them.
I still wonder, if someone did ever try to set all necessary compile flags for HDMI and give it a try with the settings i posted in my first thread. So i guess i'll have to do it...
Maybe it's all nonsense and the sources of Exynos HAL which are used by the AOSP ROMs are completely unusable, if it comes to HDMI implementation.
On the other hand there's Hardkernel's odroid platform which has a working HDMI port.
So what's the secret here?
Cheers,
scholbert
@pulser_g2 here please
Seems there is already something on its way
https://gerrit.nameless-rom.org/#/c/13927/
Gesendet von meinem GT-N7105 mit Tapatalk
Hi DerTeufel1980,
thanks for pointing to this patchset... i've already seen some other related patches some days ago.
Looks promising and hopefully this time these hacks will be successful!
Though i'm not sure about the management of the i2c ports at kernel level or maybe i just don't understand its mapping.
While it is correct that the MHL PHY is connected to the physical interface i2c-5 (the pins), it seems that the kernel uses some virtualisation based on the devices address connected to this port...
AFAIK Exynos 4412 got five physical I2C ports, which are used by a variety of physical devices (the real chips).
Each physical device should have a unique i2c address to get addressed by the CPU.
In the end we got multiple chips with different addresses connected to the physical ports which are presented as virtual device starting from i2c-0 up to i2c-21.
So if i interpret the sources correctly, the device id for DDC function should be i2c-15 at userland, or better spoken: Android world.
But as already stated maybe i'm wrong here...
Time will show
Thanks for contributing!!
EDIT:
Just contacted one of the hard working developers at Nameless ROM and he pointed me to another more frustrating issue, which is the missing source code for HWC.
See this information (which is quite old, but you need to find it ) which covers the Exynos CPU's in general:
https://plus.google.com/+AndrewDodd/posts/DHg5z62CHHu
So this snippet says it all:
Edit - HDMI
Insignal's latest reference source has new HDMI code. However, it's tightly integrated with HWC. As covered above, HWC is totally broken in their source release. No HWC, no HDMI.
Click to expand...
Click to collapse
EDIT2:
Some more tech talk to understand the flaw:
https://jira.cyanogenmod.org/browse/ESDB-1
Cheers,
scholbert
Hey there... it's me again
I thought about missing source code and how all stuff get's arranged in the variety of ROM's.
Especially MALI, HWC and proprietary stuff...
Quite irritating though because i'm no hardcore software developer :angel:
Anyway found this:
http://forum.xda-developers.com/showpost.php?p=55809089&postcount=1508
In other words, there is some HWC source code for exynos4.
Why was it dropped then and latest release of Nameless Lollipop ROM stepped back to the older MALI release?
This led to a more proprietary codebase.
I read about r4p0 would not be the best choice for mobile device or is there another reason
Please leave a comment, if you know more about it.
Would be nice to have some open discussion here anyway...
Have fun!
scholbert
The problem came with r4p0 when the proprietary HWC blob was made working with the kernel rebase from fni1 source drop of n7100. The amount of glitches occurring were too high, and the r4p0 drivers used in the device were blobs. There aren't any display related open source Hals for exynos to have a reference from and fix the graphics part having glitches.
As is already notable with chrome, GPU rasterization is broken and had even more issues with newer blobs, which actually even I'm not sure of why so. R3p2 drivers we use actually are based on a newer api as compared to r4p0 and as a result, the blobs are more updated than the r4p0 taken from the Odroid board.
̿ ̿̿’̿’\̵͇̿̿\з==(*͡° ͜ʖ ͡°)==ε/̵͇̿̿/’̿’̿ ̿ ̿̿*

Software Development Developing an OBD2/Canbus data logger

So I wanted to implement something like TeslaMate for my UIS7862. The idea being to be able to visualize trips, and various vehicle stats from Grafana (and maybe a live location tracker).
My original plan was to use TorquePro to log vehicle stats + GPS location, and then to send those logs to a listening webserver for storage in Prometheus and display via Grafana. I found an Automate script to hook this into HomeAssistant here: here. However, I wanted a few additional items:
I don't have a SIM card in my radio and do not normally have it connected to my phone as a hotspot, so internet connection is intermittent and I didn't want to lose data
I wanted to be able to upload to different IP addresses depending on whether I'm connected to the home network (i.e. at home) or otspot (i.e I'm driving)
I wanted to be able to store stats from the media canbus (like fuel level) that don't seem to be available on OBD-II (at least I haven't found them for my GTI)
I wanted to learn Kotlin and write a 'real' Android app
I was successful in writing an app that would send all unsent Torque data to my home server once it connects via wifi (basically reproducing Rob's Automate script), but getting the canbus data out of the radio required more work.
I decompiled 190000000_com.syu.canbus.apk and set about learning how it worked, and trying to connect my own app.
What I found so far:
Unlike the MKC/D units which appear to communicate with the canbus module via a serial port, the FYT radios seem to use I2C
The com.syu.ms.apk is responsible for the hardware communication
the com.syu.canbus.apk connects to the com.syu.ms.toolkit Intent to access hardware data.
This Service provides a getRemoteModule() procedure which seems to provide 4 different interfaces:
0: the 'Main' interface
4: the Sound interface
7: the Canbus interface
14: the 'CanUp' interface (no idea what this is)
each interface (IRemoteModule) provides 4 commands: cmd, get, register, unregister
The 'register' command registers a callback to a specific ID. That callback will be called when the value at the ID changes.
For instance, on my GTI, ID '6' of the canbus module is the fuel-level. I can register a callback at ID=6, and that callback will be called whenever the value changes
I haven't spent time to look at the other modules, nor what the 'get' or 'cmd' functions do
With the above, I now have a rudimentay application that will fetch the Fuel level from the radio (via the Canbox). My plan is to incorporate this with the OBDII capture to create a composte data-set to upload to my prometheus database. Interestingly, the com.syu.ms.toolbox only responds back to me if I use the 'com.syu.ipc.[IModuleCallback|IRemoteModule|IRemoteToolkit' descriptor.
I will make everything above available on GitHub once I've cleaned it up a bit. It should be possible to extract any canbus data the radio has (along with other internal state depending on what the other modules expose). However, what I've learned is that every CanBox has a different interface and presents diferent data, so the effort to make a generic interface would be very high and beyond the scope of what I plan to do. There are about 2500 unique CanBoxes listed in FinalCanbus. I see about 600 unique classes implementing these modules, each of which implements a different set of registerable IDs.
I plan to add an interface to register any ID if you know what you are looking for to my app. I think @surfer63 could do the same to FytHwOneKey if they were so inclined, but without a table of which features are available it would only likely benefit programmers.
I'll update this post with a GitHub link once available, but I thought there might be some interest in the canbus analysis stuff.
Here is the GitHub repository for the Canbus access library: https://github.com/AxesOfEvil/FYTCanbusMonitor
The CanBox ID is specified by ID=1000.
The low 16 bits appear to specify the canbox type, and the upper 16bits seem to represent the car make/model. This mapping happens in syu.ms.module.canbus.HandlerCanbus with the name mapping in module.canbus.FinalCanbus
Here is an example of the IDs for (some) Reise RZS CanBox to give an idea of what type of data is available:
Code:
U_CUR_OIL_EXPEND 0
U_MISC_BEGIN 0
U_LOW_OIL_WARN 1
U_LOW_BATTERY_WARN 2
U_LIFE_BELT_WARN 3
U_CLEAN_FLUIT_WARN 4
U_HANDLE_BRAKE_WARN 5
U_RESIDUAL_OIL 6
U_BATTERY_VOLTAGE 7
U_DRIVE_MILE 8
U_PARK 9
U_RADAR_MUTE 10
U_CUR_SPEED 11
U_ENGINE_SPEED 12
U_OUT_TEMP 13
U_AIR_BEGIN 14
U_AIR_POWER 14
U_MISC_END 14
U_AIR_BIG_WIND_LIGHT 15
U_AIR_LITTLE_WIND_LIGHT 16
U_AIR_AC 17
U_AIR_MAX 18
U_AIR_CYCLE 19
U_AIR_DUAL 20
U_AIR_REAR 21
U_AIR_BLOW_UP 22
U_AIR_BLOW_BODY 23
U_AIR_SHOW 24
U_AIR_BLOW_FOOT 25
U_AIR_WIND_LEVEL 26
U_AIR_TEMP_LEFT 27
U_AIR_TEMP_RIGHT 28
U_AIR_AQS 29
U_AIR_SEAT_HEAT_LEFT 30
U_AIR_REAR_LOCK 31
U_AIR_AC_MAX 32
U_AIR_SEAT_HEAT_RIGHT 33
U_AIR_TEMP_OUT 34
U_AIR_AUTO 35
U_AIR_END 36
U_DOOR_BEGIN 37
U_DOOR_ENGINE 37
U_DOOR_FL 38
U_DOOR_FR 39
U_DOOR_RL 40
U_DOOR_RR 41
U_DOOR_BACK 42
U_DOOR_END 43
U_AIR_FRONT 44
U_AIR_BLOW_MODE 45
U_CNT_MAX 46
AxesofEvil said:
I plan to add an interface to register any ID if you know what you are looking for to my app. I think @surfer63 could do the same to FytHwOneKey if they were so inclined, but without a table of which features are available it would only likely benefit programmers.
Click to expand...
Click to collapse
Nice work you are doing here.
But I do not know what you mean with above statement.
For further reading: lbdroid did some reverse engineering in 2006.
You might take a look at some of his repos: https://github.com/lbdroid/MCUd
In that github/readme are 5 other repos. They are outdated, but might still give you some clues.
surfer63 said:
Nice work you are doing here.
But I do not know what you mean with above statement.
For further reading: lbdroid did some reverse engineering in 2006.
You might take a look at some of his repos: https://github.com/lbdroid/MCUd
In that github/readme are 5 other repos. They are outdated, but might still give you some clues.
Click to expand...
Click to collapse
Sorry, maybe that was inappropriate. I guess I was thinking about ways to give users access to the canbox data since Tasker doesn't seem able to hook into services this way. One use case would be direct access to steering wheel buttons from the canbox (my understanding is that in some cases FwHwOneKey can't handle canbus related buttons...maybe I'm wrong). Or, perhaps there isn't really any use at all for this info to trigger user applications.
I know there was a request to access Canbox data for widgets (for instance to be able to display the outside temperature on a custom screen). This method should be able to support something like that, but I have no idea if there is an existing app that could make use of it. Maybe I could write a proxy that would turn service updates into system broadcast events? Just spitballing here.
Wow, it’s really communicate with canbus from user apps?
May be there is way to read can data, like we can see in develop mode
Sdese2000 said:
Wow, it’s really communicate with canbus from user apps?
May be there is way to read can data, like we can see in develop mode
Click to expand...
Click to collapse
To be clear, I only have access to whatever the canbox has already decoded (and the radio has accepted), at least on my vehicle, thee is a lot more CAN traffic that is ignored. What CAN data do you see in develop mode? I am not aware of this.
AxesofEvil said:
Sorry, maybe that was inappropriate. I guess I was thinking about ways to give users access to the canbox data since Tasker doesn't seem able to hook into services this way. One use case would be direct access to steering wheel buttons from the canbox (my understanding is that in some cases FwHwOneKey can't handle canbus related buttons...maybe I'm wrong). Or, perhaps there isn't really any use at all for this info to trigger user applications.
Click to expand...
Click to collapse
Not inappropiate at all. I just didn't get what you meant.
And yes: The BT like commands are still a big misunderstanding (for me that is). I think that could very well be a combi of activity, canbus and "something else"
But as my unit doesn't have buttons anymore, and neither my previous one, I don't spend time on my own app anymore.
AxesofEvil said:
To be clear, I only have access to whatever the canbox has already decoded (and the radio has accepted), at least on my vehicle, thee is a lot more CAN traffic that is ignored. What CAN data do you see in develop mode? I am not aware of this.
Click to expand...
Click to collapse
In Head Unit settings there is trigger, if turn on it, can logs will appear on the screen.
If found some code in com/syu/util/DebugViev.jave that provide it
Spoiler
package com.syu.util;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.p000v4.internal.view.SupportMenu;
import android.view.View;
import android.view.WindowManager;
import java.util.Locale;
public class DebugView extends View {
private int CELL_HEIGHT = 35;
int[] COLOR = {SupportMenu.CATEGORY_MASK, -1, -16711936, -256, -16776961};
private final int MAX = 16;
private final int TEXT_SIZE = 23;
/* access modifiers changed from: private */
public int[] mColors = new int[16];
/* access modifiers changed from: private */
public int mCount;
private boolean mDbg = false;
/* access modifiers changed from: private */
public int mLastIndex;
private WindowManager.LayoutParams mLp = ToolkitApp.buildOverlayLayoutParams(-1, -1);
/* access modifiers changed from: private */
public int mMsgCnt;
/* access modifiers changed from: private */
public String[] mMsgs = new String[16];
private Paint mPaint = new Paint();
public DebugView(Context context) {
super(context);
init();
}
private void init() {
this.mPaint.setAntiAlias(true);
this.mPaint.setTextSize(23.0f);
this.mPaint.setColor(-1);
}
public void setDbg(boolean flag) {
this.mDbg = flag;
}
public boolean isDbg() {
return this.mDbg;
}
public WindowManager.LayoutParams getWindowLayoutParams() {
return this.mLp;
}
public void msg(String msg) {
if (this.mDbg && msg != null) {
HandlerUI.getInstance().post(new MessageHelper(msg));
}
}
public void msg2(String msg) {
if (this.mDbg && msg != null) {
HandlerUI.getInstance().post(new MessageHelper(msg));
}
}
public void msgHex(String str, byte[] data, int start, int length) {
if (this.mDbg && data != null) {
if (data.length - start < length) {
length = data.length - start;
}
String msg = String.valueOf(str) + " * ";
for (int i = 0; i < length; i++) {
String c = Integer.toHexString(data[start + i] & 255).toUpperCase(Locale.CHINA);
if (c.length() < 2) {
c = "0" + c;
}
msg = String.valueOf(msg) + c + " ";
}
HandlerUI.getInstance().post(new MessageHelper(msg));
}
}
public void msgHex(String str, int[] data, int start, int length) {
if (this.mDbg && data != null) {
if (data.length - start < length) {
length = data.length - start;
}
String msg = String.valueOf(str) + " * ";
for (int i = 0; i < length; i++) {
String c = Integer.toHexString(data[start + i] & 255).toUpperCase(Locale.CHINA);
if (c.length() < 2) {
c = "0" + c;
}
msg = String.valueOf(msg) + c + " ";
}
HandlerUI.getInstance().post(new MessageHelper(msg));
}
}
private class MessageHelper implements Runnable {
private String mMessage;
public MessageHelper(String msg) {
this.mMessage = msg;
}
public void run() {
DebugView debugView = DebugView.this;
debugView.mLastIndex = debugView.mLastIndex + 1;
DebugView debugView2 = DebugView.this;
debugView2.mCount = debugView2.mCount + 1;
if (DebugView.this.mLastIndex > 15) {
DebugView.this.mLastIndex = 0;
}
if (DebugView.this.mCount > 16) {
DebugView.this.mCount = 16;
}
DebugView debugView3 = DebugView.this;
debugView3.mMsgCnt = debugView3.mMsgCnt + 1;
DebugView.this.mMsgs[DebugView.this.mLastIndex] = String.format("%06d @ %s", new Object[]{Integer.valueOf(DebugView.this.mMsgCnt), this.mMessage});
DebugView.this.mColors[DebugView.this.mLastIndex] = DebugView.this.COLOR[DebugView.this.mLastIndex % DebugView.this.COLOR.length];
DebugView.this.invalidate();
}
}
/* access modifiers changed from: protected */
public void onDraw(Canvas canvas) {
if (this.mCount != 0) {
int count = this.mCount;
int firstIndex = (this.mLastIndex - count) + 1;
if (firstIndex < 0) {
firstIndex += 16;
}
if (firstIndex + count > 16) {
int rightCount = 16 - firstIndex;
int leftCount = count - rightCount;
for (int i = 0; i < rightCount; i++) {
int index = firstIndex + i;
this.mPaint.setColor(this.mColors[index]);
canvas.drawText(this.mMsgs[index], (float) 5, (float) ((i + 1) * this.CELL_HEIGHT), this.mPaint);
}
for (int i2 = 0; i2 < leftCount; i2++) {
this.mPaint.setColor(this.mColors[i2]);
canvas.drawText(this.mMsgs[i2], (float) 5, (float) ((rightCount + i2 + 1) * this.CELL_HEIGHT), this.mPaint);
}
return;
}
for (int i3 = 0; i3 < count; i3++) {
int index2 = firstIndex + i3;
this.mPaint.setColor(this.mColors[index2]);
canvas.drawText(this.mMsgs[index2], (float) 5, (float) ((i3 + 1) * this.CELL_HEIGHT), this.mPaint);
}
}
}
}
I have updated the OP with a link to the GitHub library (here). The library is not really meant to be used standalone, but instead to be incorporated into other projects. I haven't posted the code for the logger as there is still quite a bit more to do on that side.
The library repo does include an example application which will simply log every message received to the screen/logfile (in /Downloads). It is very inefficient since it just blindly asks for every possible ID regardless of whether it is actually available for a given CanBox or not, but is meant to give a quick idea of what data is available and a short example of how to use the library. The latest compiled APK can be found here: https://github.com/AxesOfEvil/FYTCanbusMonitor/releases
I found this interesting tidbit today:
It seems to be that arbitrary commands can be sent to the canbus through the radio via sys.ms by calling ToolkitDev.writeMcu(0xE3, PID, data-len, data0, data1, ...) (where data can be 1-8 bytes).
Edit: ToolkitDev.writeMcu(0xE3, ...) seems to write commands to the canbox module. As I don't have the source for teh module, I'm not sure how it handles these commands, but they don't g out verbatim on the canbus itself.
There is also ToolkitDev.writeCanbusDirect, but this may send commands via an OBDII dongle...Edit: this seems to just directly send raw commands to the CanBox. It is similar to the above but requires manually calculating the entire packet (including checksum)
I have not found a way to pass arbitrary data from an external app through an intent to allow other apps to send arbitrary canbus commands, but with a hacked syu.ms, it probably means I can eliminate the DynAudio AMP control box I had to make to get my audio working. And that with more hacking, it may be possible to send GPS directions and music info to the HUD.
AxesofEvil said:
The CanBox ID is specified by ID=1000.
The low 16 bits appear to specify the canbox type, and the upper 16bits seem to represent the car make/model. This mapping happens in syu.ms.module.canbus.HandlerCanbus with the name mapping in module.canbus.FinalCanbus
Here is an example of the IDs for (some) Reise RZS CanBox to give an idea of what type of data is available:
Code:
U_CUR_OIL_EXPEND 0
U_MISC_BEGIN 0
U_LOW_OIL_WARN 1
U_LOW_BATTERY_WARN 2
U_LIFE_BELT_WARN 3
U_CLEAN_FLUIT_WARN 4
U_HANDLE_BRAKE_WARN 5
U_RESIDUAL_OIL 6
U_BATTERY_VOLTAGE 7
U_DRIVE_MILE 8
U_PARK 9
U_RADAR_MUTE 10
U_CUR_SPEED 11
U_ENGINE_SPEED 12
U_OUT_TEMP 13
U_AIR_BEGIN 14
U_AIR_POWER 14
U_MISC_END 14
U_AIR_BIG_WIND_LIGHT 15
U_AIR_LITTLE_WIND_LIGHT 16
U_AIR_AC 17
U_AIR_MAX 18
U_AIR_CYCLE 19
U_AIR_DUAL 20
U_AIR_REAR 21
U_AIR_BLOW_UP 22
U_AIR_BLOW_BODY 23
U_AIR_SHOW 24
U_AIR_BLOW_FOOT 25
U_AIR_WIND_LEVEL 26
U_AIR_TEMP_LEFT 27
U_AIR_TEMP_RIGHT 28
U_AIR_AQS 29
U_AIR_SEAT_HEAT_LEFT 30
U_AIR_REAR_LOCK 31
U_AIR_AC_MAX 32
U_AIR_SEAT_HEAT_RIGHT 33
U_AIR_TEMP_OUT 34
U_AIR_AUTO 35
U_AIR_END 36
U_DOOR_BEGIN 37
U_DOOR_ENGINE 37
U_DOOR_FL 38
U_DOOR_FR 39
U_DOOR_RL 40
U_DOOR_RR 41
U_DOOR_BACK 42
U_DOOR_END 43
U_AIR_FRONT 44
U_AIR_BLOW_MODE 45
U_CNT_MAX 46
Click to expand...
Click to collapse
Where did these IDs come from? Did you find one for Illumination/Headlights?
The IDs came out of the source code for 190000000_com.syu.canbus.apk
The IDs are canbox and probably vehicle specific, so such info may be available, but you need to identify exactly what you are looking for.
Use JadX or BytecodeViewer or a similar application to analyze the apk file above, and look in app/src/main/java/module/canbus for the appropriate Canbox for your vehicle

Categories

Resources