Arduino - Converting byte array to string/char array - android

I'm currently working on communication between devices using HID over a usb cable. I am sending a string that is UTF-8 encoded from an Android device, and would like to receive and read it on my Arduino Leonardo.
My problem is that I am unable to get the received message into any other type. I need to do a human readable string comparison as I'm sending a variety of commands to the Arduino. The IDE either has a type mismatch problem regardless of how I try to convert the received message. I've tried many different things but I will post one as an example. I'm sure there is something I missing that's keeping me from getting this!
int n;
n = RawHID.recv(buffer, 0); // 0 timeout = do not wait
if (msUntilNextSend > 2000) {
msUntilNextSend = msUntilNextSend - 2000;
// String mystr = "";
// byte charbuff[10];
//
// for (int i = 0; i < 64; i++)
// {
// mystr.concat((char) buffer[i]);
// }
//
// mystr.toCharArray(charbuff, 10);
char readin[64] = { ' ' };
readin = (char *)buffer;
String myString = String((char *)buffer);
if (strcmp(readin, "test") == 0)
{
String resp = "response";
resp.getBytes(buffer, 64);
n = RawHID.send(buffer, 100);
}
I've included some comments with bits of a different approach but as I mentioned, I have been unsuccessful in my attempts. Any insight is appreciated!

Related

Getting SHOUTcast Meta Data Manually

I would like to scan for SHOUTcast meta data myself. I realise there cool classes such as IcyStreamMeta etc but I would like to know why I cannot see the data myself.
I am using this URL (have tried others too):
http://www.shoutcastunlimited.com:8512/
My understanding is that I should see meta data within the audio stream data - especially when a radio station changes the current tune.
What I've tried to do is output sequences of printable ASCII character to see if I can see keywords such as "StreamTitle" but all I can see if anything is "LAME".
My code below is less than ideal but is there are reason why I am not seeing "StreamTitle" or other meaningful words?
public void retreiveMetadata()
{
try
{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url( mStreamUrl ).build();
Response response = client.newCall( request ).execute();
mStream = response.body().byteStream();
// This returns 200 as expected
ContextActivity.LogDebugf( "ICY RESPONSE: %d\n", response.code() );
if( abBuffer == null )
abBuffer = new byte[ nBufferSize ];
for( ;; )
{
// Read data INTO the buffer
int nRead = mStream.read( abBuffer, 0, nBufferSize );
//ContextActivity.LogDebugf( "ICY Data Read: %d\n", nRead );
int nPrintableStart = -1;
int nPrintableCount = 0;
for( int i = 0; i < nRead; i ++ )
{
// Look for printable chars only
if( ( abBuffer[ i ] >= ' ' ) && ( abBuffer[ i ] < '~' ) )
{
if( nPrintableStart < 0 )
{
nPrintableStart = i;
nPrintableCount = 0;
}
nPrintableCount ++;
}
else
{
// End of printable range
if( nPrintableCount >= 11 )
{
String sMeta = new String( abBuffer, nPrintableStart, nPrintableCount, "UTF-8" );
ContextActivity.LogDebugf( "ICY[%s]\n", sMeta );
}
nPrintableStart = -1;
nPrintableCount = 0;
}
}
}
}
catch( Exception e )
{
ContextActivity.LogDebugf( "ICY Exception[%s]\n", e.toString() );
}
}
Here are some "LAME" examples:
02-24 16:58:01.570: I/System.out(26965): ICY[LAME3.98.4UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU|]
02-24 16:58:01.580: I/System.out(26965): ICY[LAME3.98.4UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU|\]
02-24 16:58:01.590: I/System.out(26965): ICY[LAME3.98.4IUb\]
I don't see any place where you are actually requesting metadata. If you don't request it, the server won't send it. Add this header to your request:
Icy-MetaData: 1
In the response, you'll get a header back (assuming the server supports metadata) that says:
Icy-MetaInt: 8192
Whatever that number is (8192 in this case, which is a typical figure) is the number of bytes in between each metadata block.
The first byte in the metadata block indicates the size of the metadata block. If it's 0x00, then there is no metadata and it's back to audio data for the size of the interval. If it says 0x02 or some other non-zero value, multiply that by 16, and that's the number of bytes (NUL [0x00] padded) of text metadata, in a key="value" sort of format. StreamTitle is the only one that's all that meaningful these days. Some streams have been known to include other data, often for internal tracking.

libusb - How to select an alternate setting of a usb-soundcard for stereo recording?

I have a USB sound card that has the following setup and allows for stereo recording with 48000hz 2 channels 16 bit, so I'm trying to set it up that way:
UsbConfiguration[mId=1,mName=null, mAttributes=160, mMaxPower=50,
mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=1,mSubclass=1,mProtocol=0,
mEndpoints=[]
UsbInterface[mId=1,mAlternateSetting=0,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[]
UsbInterface[mId=1,mAlternateSetting=1,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=384,mInterval=1]]
UsbInterface[mId=1,mAlternateSetting=2,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=576,mInterval=1]]
UsbInterface[mId=1,mAlternateSetting=3,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=192,mInterval=1]]
UsbInterface[mId=2,mAlternateSetting=0,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[]
UsbInterface[mId=2,mAlternateSetting=1,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=196,mInterval=1]]
UsbInterface[mId=2,mAlternateSetting=2,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=294,mInterval=1]]
UsbInterface[mId=2,mAlternateSetting=3,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=388,mInterval=1]]
UsbInterface[mId=2,mAlternateSetting=4,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=582,mInterval=1]]
UsbInterface[mId=3,mAlternateSetting=0,mName=null,mClass=3,mSubclass=0,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=130,mAttributes=3,mMaxPacketSize=16,mInterval=16]
]
]
I'm trying to select and use the incoming interface with the alternate setting for stereo input and do the same thing with the interface for the stereo output.
For the input, I've tried to do it natively with the following code:
int AndroidUSBAudioIO_start(int sampleRate, int bufferSize, void *callback, void *clientData) {
int rc = -1;
if (androidUSBAudioIO == NULL) {
androidUSBAudioIO = (AndroidUSBAudioIOInternals *) malloc(sizeof(AndroidUSBAudioIOInternals));
}
androidUSBAudioIO->samplerate = sampleRate;
androidUSBAudioIO->buffersize = bufferSize;
androidUSBAudioIO->callback = (audioUSBProcessingCallback *) callback;
androidUSBAudioIO->clientData = clientData;
androidUSBAudioIO->maruStream = 0;
androidUSBAudioIO->isSetup = 0;
androidUSBAudioIO->isPlaying = 0;
rc = libusb_init(NULL);
if (rc < 0) {
}
androidUSBAudioIO->deviceHandle = libusb_open_device_with_vid_pid(NULL, VID, PID);
if (!androidUSBAudioIO->deviceHandle) {
rc = -1;
goto out;
}
rc = libusb_reset_device(androidUSBAudioIO->deviceHandle);
if (rc < 0) {
goto out;
}
rc = libusb_set_configuration(androidUSBAudioIO->deviceHandle, 1);
if (rc < 0) {
}
rc = libusb_kernel_driver_active(androidUSBAudioIO->deviceHandle, IFACE_NUM);
if (rc == 1) {
rc = libusb_detach_kernel_driver(androidUSBAudioIO->deviceHandle, IFACE_NUM);
if (rc < 0) {
goto out;
}
}
rc = libusb_claim_interface(androidUSBAudioIO->deviceHandle, IFACE_NUM);
if (rc < 0) {
goto out;
}
rc = libusb_set_interface_alt_setting(androidUSBAudioIO->deviceHandle, 1, 2);
if (rc < 0) {
printf("libusb_claim_interface: %s.\n", libusb_error_name(rc));
goto out;
}
...
I'm getting the following error at when setting the alternate interface:
Fatal signal 11 (SIGSEGV) at 0x0000001d (code=1), thread 10303
and also tried to do it from java with the following code upon receiving the permission to use the device:
UsbDeviceConnection mUsbDevConn = mUsbManager.openDevice(mAudioDevice);
int mReqType = 0x01; //
int mRequest = 0x0B; // SET_INTERFACE USB SPEC CONSTANT
int mValue = 0x02; // alt settings
int mIndex = 0x01; // interface nr
byte[] mBuffer = null;
int mLength = 0;
int mTimout = 1000;
mUsbDevConn.controlTransfer(UsbConstants.USB_DIR_OUT | mReqType, mRequest, mValue, mIndex, mBuffer, mLength, mTimout);
I'm getting the following error:
Error (status 6: **UNKNOWN**)
What am I missing?
I think it would be highly unusual for the libusb_set_interface_alt_setting call itself to cause the SIGSEGV. I would expect that either a prior call would cause this, or the SIGSEGV is an indirect effect of the call. That is, this call changes the alternate setting, which effectively starts the transfer of audio data. If the buffers, other data structures or the callback are not setup correctly a SIGSEGV may result.
In your situation, I would put more debug messages in the code, including in the library and your callback to try to narrow down the last thing before the crash.
If the code was working for a "mono" device, have a look at what has changed in the move to "Stereo". Perhaps the data-packet size (buffers) needs to be larger.
As far as the Java version is concerned, the error 6 may be related to the fact that you don't seem to be detaching any kernel drivers or claiming the interface before trying to change the alternate setting.
In the past I found it necessary to detach kernel drivers from each and every interface including HID interfaces to free up the allocated bus bandwidth before starting the audio.
Finally, if the free version of usbEffects (Android App) works with this device, you can connect adb to the phone via Wi-Fi and run the app with the device connected to see the debug messages that will tell if the requestType, request etc parameters are correct for this hardware.

Encryption on open Source VoIP Android

This is with reference to sipdroid data encrypt failed
I tried using XOR operation instead of reverse byte code for send packets and receive packets in SipdroidSocket.class.
I experienced same issue(too much noise)
Please guide me in encrypting and decrypting packets in SipdroidSocket.class
Sorry for late reply.I am posting the snippets of the code I tried. Please refer the original RtpSocket.java and SipdroidSocket.java classes for complete view. I am just putting the snippets here.
In RtpSocket.java , I took a static value and collected the packet's header length. Then used this header length in SipdroidSocket.java so as to remove the header part prior tweaking with the payload:
In SipdroidSocket.java, following editing were done in Send and Receive functions:
public void receive(DatagramPacket pack) throws IOException {
if (loaded) {
impl.receive(pack);
byte[] b = pack.getData(); // fetch data from receiver
int len = RtpSocket.header;
pack.setData(do_something(b, len)); // do the XORing to retrieve
// original data
} else {
super.receive(pack);
byte[] b = pack.getData();
int len = RtpSocket.header;
pack.setData(do_something(b, len));
}
}
public void send(DatagramPacket pack) throws IOException {
byte[] b = pack.getData(); // fetch original data
int len = RtpSocket.header;
pack.setData(do_something(b, len)); // replace with tweaked data
if (loaded)
impl.send(pack);
else
super.send(pack);
}
private byte[] do_something(byte[] b, int len) {
// TODO Auto-generated method stub
int new_buff_len = b.length - len;
byte[] new_buff = new byte[new_buff_len];
int i = 0;
for (i = len; i < b.length; i++) // separating header values
{
new_buff[i] = (byte) (b[i] ^ 0x43); // XORing original packet
// payload before sending and
// after receiving to get
// original data on both sides
}
return new_buff;
}
Kindly , try it and suggest me please.
Finally it worked ! Had to meddle with the other parts of the code . XOR operation now works fine and have attained the objective.

Find mobile device identifier (UDID or Android id)

I want to find out the list of mobile devices which are all click my ad. Based on the details I want to re-target them
So I need to capture their identifier(UDID in ios and Android id in android phone) in order to identify them.
Can anyone suggest me good method or prefer any better way to achieve the above.
For Android, you should check this thread :
Will TelephonyManger.getDeviceId() return device id for Tablets like Galaxy Tab...?
Jorgesys' answer seems clean.
ANDROID:
I am using this and seems to be working fine.
public static String getDeviceAndroidID(Context context)
{
String android_id = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
if(android_id != null)
return android_id;
else
return "";
}
iOS:
For iOS version less than 7 I am using MAC address of the device. From iOS version 7 apple is providing a unique ID for this purpose.
(NSString *)getMacAddress
{
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
{
NSString *strUID = nil;
if(strUID == nil) strUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
return strUID;
}
int mgmtInfoBase[6];
char *msgBuffer = NULL;
size_t length;
unsigned char macAddress[6];
struct if_msghdr *interfaceMsgStruct;
struct sockaddr_dl *socketStruct;
NSString *errorFlag = nil;
// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET; // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE; // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK; // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST; // Request all configured interfaces
// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = #"if_nametoindex failure";
else
{
// Get the size of the data available (store in len)
if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = #"sysctl mgmtInfoBase failure";
else
{
// Alloc memory based on above call
if ((msgBuffer = malloc(length)) == NULL)
errorFlag = #"buffer allocation failure";
else
{
// Get system information, store in buffer
if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
errorFlag = #"sysctl msgBuffer failure";
}
}
}
// Befor going any further...
if (errorFlag != nil)
{
free(msgBuffer);
if(ENABLE_LOG) DLog(#"Error: %#", errorFlag);
return errorFlag;
}
// Map msgbuffer to interface message structure
interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
// Map to link-level socket structure
socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
// Copy link layer address data in socket structure to an array
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);
// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:#"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2],
macAddress[3], macAddress[4], macAddress[5]];
//if(ENABLE_LOG) DLog(#"Mac Address: %#", macAddressString);
// Release the buffer memory
free(msgBuffer);
return macAddressString;
}

Android/PHP - Encryption and Decryption

I'm struggeling with code from this page: http://www.androidsnippets.com/encrypt-decrypt-between-android-and-php
I want to send data from a server to an Android application and vice versa, but it should be sent as an encrypted string. However, I manage to encrypt and decrypt the string in PHP. But on Android the application crashes with the following error message when decrypting:
java.lang.Exception: [decrypt] unable to parse ' as integer.
This error occours here in the for-loop:
public static byte[] hexToBytes(String str) {
if (str==null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i=0; i<len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
}
System.out.println("Buffer: " + buffer);
return buffer;
}
}
This is by the way the string that should be decrypted: f46d86e65fe31ed46920b20255dd8ea6
You're talking about encrypting and decrypting, but you're showing code which simply turns numeric bytes (such as 0x4F) into strings (such as "4F") -- which may be relevant to your transfer of data (if you cannot transfer binary format), but completely unrelated to encryption/decryption.
Since the Android code you have contains only a single Integer parse, have you examined the input you're giving it? str.substring(i*2,i*2+2) apparently contains data other than [0-9A-F] when the exception occurs. You should start by examining the string you've received and comparing it to what you sent, to make sure they agree and they only contain hexadecimal characters.
Edit -- passing the string "f46d86e65fe31ed46920b20255dd8ea6" through your hexToBytes() function works flawlessly. Your input is probably not what you think it is.

Categories

Resources