588 lines · 15.0 KB · Text
RawDownload
/* TODO:   complete translation from gsm to ascii and ascii to gsm   handle sending/receiving multiple text messages and checking length of messages*/ /*#include	"dat.h"#include	"fns.h"#include	"error.h"#include	"version.h"#include	"mp.h"#include	"libsec.h"#include	"keyboard.h"*/#include        <stdio.h>#include <cutils/sockets.h>#include <stdlib.h>#include <telephony/ril.h>#include <cutils/jstring.h>#include <arpa/inet.h>#include <libgen.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> #define RESPONSE_SOLICITED 0#define RESPONSE_UNSOLICITED 1 /* Parcel-handling code */#define PAD_SIZE(s) (((s)+3)&~3) struct parcel_t {	char *data;	size_t offset;	size_t capacity;	size_t size;}; void parcel_init(struct parcel_t *p){	p->data = malloc(sizeof(int32_t)); // arbitrary size to start with	p->size = 0;	p->capacity = sizeof(int32_t);	p->offset = 0;} int parcel_grow(struct parcel_t *p, size_t size){	char *new = realloc(p->data, p->capacity + size); 	if(new == NULL) {		return -1;	}	p->data = new;	p->capacity += size;	return 0;} int32_t parcel_r_int32(struct parcel_t *p){	int32_t ret;	ret = *((int32_t *) (p->data + p->offset));	p->offset += sizeof(int32_t);	return ret;} int parcel_w_int32(struct parcel_t *p, int32_t val){	for(;;) {		printf("parcel_w_int32(%d): offset = %d, cap = %d, size = %d\n",		       val, p->offset, p->capacity, p->size);		if(p->offset + sizeof(int32_t) < p->capacity) {			// There's enough space			*((int32_t *) (p->data + p->offset)) = val;			p->offset += sizeof(int32_t);			p->size += sizeof(int32_t);			break;		} else {			// Grow data and retry			if(parcel_grow(p, sizeof(int32_t)) == -1) {				return -1;			}		}	}	return 0;} int parcel_w_string(struct parcel_t *p, char *str){	char16_t *s16;	size_t s16_len;	size_t len; 	if(str == NULL) {		parcel_w_int32(p, -1);		return 0;	}	s16 = strdup8to16(str, &s16_len);	if(parcel_w_int32(p, s16_len) == -1) {		return -1;	}	len = (s16_len + 1) * sizeof(char16_t);	for(;;) {		size_t padded = PAD_SIZE(len);		printf("parcel_w_string(\"%s\"): offset %d, cap %d, size %d\n",		       str, p->offset, p->capacity, p->size);		if(p->offset + len < p->capacity) {			// There's enough space			memcpy(p->data + p->offset, s16, s16_len * sizeof(char16_t));			*((char16_t *) (p->data + p->offset + len)) = 0;			p->offset += padded;			p->size += padded;			if (padded != len) {				printf("Writing %ld bytes, padded to %ld\n", len, padded);#if BYTE_ORDER == BIG_ENDIAN				static const uint32_t mask[4] = {					0x00000000, 0xffffff00, 0xffff0000, 0xff000000				};#endif#if BYTE_ORDER == LITTLE_ENDIAN				static const uint32_t mask[4] = {					0x00000000, 0x00ffffff, 0x0000ffff, 0x000000ff				};#endif				//printf("Applying pad mask: %p to %p\n", (void*)mask[padded-len],				//    *reinterpret_cast<void**>(data+padded-4));				*((uint32_t*)(p->data+p->offset+padded-4)) &= mask[padded-len];			}			break;		} else {			// Grow data and retry			if(parcel_grow(p, padded) == -1) {				free(s16);				return -1;			}		}	}	free(s16);	return 0;} char *parcel_r_string(struct parcel_t *p){	char *ret;	int len = parcel_r_int32(p);	printf("parcel_r_string: len = %d\n", len);	ret = strndup16to8((char16_t *) (p->data + p->offset), len);	p->offset += PAD_SIZE((len + 1) * sizeof(char16_t));	return ret;} size_t parcel_data_avail(struct parcel_t *p){	return (p->size - p->offset);} /* Received SMS - we get a hex string representation of the data.   Roughly, the layout of the data is:   1 byte - length of SMS center information   1 byte - the format of the number (91 is the standard)   (length above - 1) bytes - the number, nibble-swapped and padded with an   f if needed   1 byte - properties of the message, generally we can ignore this   1 byte - length of sender number (in digits, not bytes)   variable bytes - sender number, nibble-swapped and padded if needed   1 byte - protocol identifier - can ignore this probably   1 byte - data coding scheme - again can hopefully be ignored   7 bytes - timestamp, again nibble-swapped: y, m, d, h, m, s, timezone   * timezone is in units of +15 min vs. GMT. If most sig. bit is   1, value is in units of -15 min vs. GMT.   1 byte - length of message in characters (NOT in bytes)   rest of bytes - message. if ASCII 7-bit, compacted to save space through   an encoding mechanism.   For more information see http://www.dreamfabric.com/sms/ or GSM 03.38*/ struct recvd_sms {	char *src_num;	char *service_center;	char *msg;	char *timestamp;}; char gsm_to_ascii(char gsm);int decode_sms(char *hexstr, struct recvd_sms *sms);void acknowledge_sms(int fd);void send_sms(int fd, char *smsc_pdu, char *pdu);void usage(char *name);void loop_for_data(int fd); /* SMS-related functions */char gsm_to_ascii(char gsm){	switch(gsm) {	case '\0': return '@';	}} char *hexify(char *bytes, size_t len){	char *hexarray[256];	int i, j;	char *ret;	for(i = 0; i < 256; i++) {		hexarray[i] = (char *) malloc(3 * sizeof(char));		snprintf(hexarray[i], 3, "%02x", i);	}	ret = (char *) malloc((len * 2 + 1) * sizeof(char));	for(i = 0, j = 0; i < len; i++, j += 2) {		ret[j] = hexarray[(unsigned char) bytes[i]][0];		ret[j + 1] = hexarray[(unsigned char) bytes[i]][1];	}	ret[j] = '\0';	return ret;} int decode_sms(char *hexstr, struct recvd_sms *sms){	int smsc_len, src_len, curpos, msg_len;	char *endptr;	char **bytes;	char *service_center, *src_num, *timestamp, *msg;	int len, i, j, oldbits, numoldbits;	char *msgbytes;    	/* first, split the string up into hex representations of the bytes--	   this makes things much easier overall */	len = strlen(hexstr);	if(len % 2 != 0) {		fprintf(stderr, "malformed hex string passed to decode_sms\n");		return -1;	}	bytes = (char **) malloc((len / 2) * sizeof(char *));	for(i = 0; i < len / 2; i++) {		bytes[i] = (char *) malloc(3 * sizeof(char));		bytes[i][0] = hexstr[i * 2];		bytes[i][1] = hexstr[i * 2 + 1];		bytes[i][2] = '\0';	} 	// decode the service center number	smsc_len = strtol(bytes[0], &endptr, 16);	if(strcmp(bytes[1], "91")) {		fprintf(stderr, "unsupported number format for sender: %s",			bytes[1]);	}	service_center = (char *) malloc((smsc_len) * sizeof(char));	service_center[0] = '\0';	for(i = 2, j = 0; i < smsc_len + 1; i++, j += 2) {		// number is nibble-swapped		service_center[j] = bytes[i][1];		if(bytes[i][0] == 'f') { // num may be padded with 'f' at end			service_center[j + 1] = '\0';		} else {			service_center[j + 1] = bytes[i][0];		}	}	service_center[j] = '\0';	curpos = i;	sms->service_center = service_center; 	// next, decode the sender's number	src_len = strtol(bytes[curpos + 1], NULL, 16);	src_num = (char *) malloc((src_len + 1) * sizeof(char));	// convert src_len from # of digits to # of bytes	src_len = (src_len % 2 == 0) ? src_len : src_len + 1;	src_len = src_len / 2;	if(strcmp(bytes[curpos + 2], "91")) {		fprintf(stderr, "unsupported number format for sender: %s",			bytes[curpos + 2]);	}	for(i = curpos + 3, j = 0; i < curpos + 3 + src_len; i++, j += 2) {		// number is nibble-swapped		src_num[j] = bytes[i][1];		if(bytes[i][0] == 'f') { // num may be padded with 'f' at end			src_num[j + 1] = '\0';		} else {			src_num[j + 1] = bytes[i][0];		}	}	src_num[j] = '\0';	sms->src_num = src_num;	curpos = i; 	// Timestamp	timestamp = (char *) malloc(9 * sizeof(char));	for(i = curpos + 2, j = 0; i < curpos + 9; i++, j += 2) {		// number is nibble-swapped		timestamp[j] = bytes[i][1];		timestamp[j + 1] = bytes[i][0];	}	curpos = i;	timestamp[j] = '\0';	sms->timestamp = timestamp; 	// Message	msg = (char *) malloc(strtol(bytes[curpos], NULL, 16) * sizeof(char));	msg_len = len / 2 - (curpos + 1);	msgbytes = (char *) malloc((msg_len) * sizeof(char));	for(i = curpos + 1, j = 0; i < len / 2, j < msg_len; i++, j++) {		msgbytes[j] = strtol(bytes[i], NULL, 16);	}	// convert message to 8-bit ASCII	oldbits = 0;	numoldbits = 0;	for(i = 0, j = 0; i < msg_len; i++, j++) {		int numbits = (i % 7) + 1;		int newbits;		newbits = msgbytes[i] >> (8 - numbits);		newbits &= (1 << numbits) - 1;		msgbytes[i] = msgbytes[i] & ((1 << (8 - numbits)) - 1);		msgbytes[i] = msgbytes[i] << numoldbits;		msg[j] = msgbytes[i] | oldbits;		// GSM alphabet is different than ASCII alphabet		msg[j] = gsm_to_ascii(msg[j]);		if(numbits == 7) {			msg[j + 1] = newbits;			j++;			newbits = 0;			numbits = 0;		}		oldbits = newbits;		numoldbits = numbits;	}	msg[j] = '\0';	sms->msg = msg; 	// cleanup	for(i = 0; i < len / 2; i++) {		free(bytes[i]);	}	free(bytes);	free(msgbytes);	return 0;} char *encode_sms(char *destnum, char *msg){	int i, j, actual_dest_len, enc_msg_len, ret_len;	char dest_len[3];	char *dest;	char *enc_msg, *final_msg, *ret;	// dest_len is the hex representation of the length of the phone #	snprintf(dest_len, 3, "%02x", strlen(destnum));	actual_dest_len = (strlen(destnum) % 2 == 0) ? strlen(destnum) : strlen(destnum) + 1;	dest = (char *) malloc((actual_dest_len + 1) * sizeof(char));	for(i = 0; i < actual_dest_len; i += 2) {		if(destnum[i + 1] != '\0') {			dest[i] = destnum[i + 1];		} else {			dest[i] = 'f';		}		dest[i + 1] = destnum[i];	}	dest[i] = '\0';	printf("dest = %s\n", dest);	enc_msg_len = strlen(msg) - (strlen(msg) / 8);	enc_msg = (char *) malloc((enc_msg_len + 1) * sizeof(char));	for(i = 0, j = 0; i < strlen(msg); i++, j++) {		int numbits = (i + 1) % 8;		char bits;		if(numbits == 0) {			j--;			continue;		}		bits = msg[i + 1] & ((1 << numbits) - 1);		enc_msg[j] = msg[i] >> numbits - 1;			printf("once shifted by %d: %hhx\n", numbits, enc_msg[j]);		enc_msg[j] = enc_msg[j] | (bits << (8 - numbits));			printf("bits << (8 - numbits) %hhx\n", bits << (8 - numbits));		printf("%hhx\n", enc_msg[j]);		fflush(stdout);	}	final_msg = hexify(enc_msg, enc_msg_len);	ret_len = 14 + strlen(dest) + strlen(final_msg);	ret = (char *) malloc((ret_len + 1) * sizeof(char));	// FIXME: too much of the sent msg is hardcoded	snprintf(ret, ret_len + 1, "0120%s91%s0000%02x%s", dest_len, dest, strlen(msg), final_msg);	printf("%s\n", ret);	free(enc_msg);	free(final_msg);	free(dest);	return ret;} /* functions that actually belong here */ void usage(char *name){	printf("%s command [arguments]\n", name);	printf("Commands:\n");	printf("a: activate data network\n");	printf("d <number>: dial a number\n");	printf("t <number> <msg>: send an SMS message\n");} void interpret_sol_response(struct parcel_t *p, int fd){	int seq, error, i;	seq = parcel_r_int32(p);	error = parcel_r_int32(p);	printf("solicited: seq = %d error = %d\n", seq, error);	printf("%d bytes left\n", parcel_data_avail(p));	if(seq == 0) {		if(!parcel_data_avail(p)) return;		int numstr;		numstr = parcel_r_int32(p);		printf("numstr = %d\n", numstr);		for(i = 0; i < numstr; i++) {			printf("%s\n", parcel_r_string(p));		}	}} void interpret_unsol_response(struct parcel_t *p, int fd){	int resp_type;	resp_type = parcel_r_int32(p);	printf("unsolicited: type = %d, data left = %d\n", resp_type,	       parcel_data_avail(p));	if(resp_type == RIL_UNSOL_RESPONSE_NEW_SMS) {		struct recvd_sms sms;		decode_sms(parcel_r_string(p), &sms);		printf("Got SMS: %s from %s (service center %s)\n", sms.msg,		       sms.src_num, sms.service_center);		acknowledge_sms(fd);	}} void loop_for_data(int fd){	for(;;) {		int msglen, readlen, type, i;		char *buf;		struct parcel_t p;		void *pdata; 		parcel_init(&p);		if(read(fd, &msglen, sizeof(msglen)) != sizeof(msglen)) {			fprintf(stderr, "EOF while reading parcel length");		}		msglen = ntohl(msglen);		buf = (char *) malloc(msglen * sizeof(char));		readlen = read(fd, buf, msglen);		if(readlen != msglen) {			fprintf(stderr, "msglen = %d readlen = %d\n", msglen,				readlen);			fprintf(stderr,				"got too much or not enough data, aborting\n");			return;		}		for(i = 0; i < readlen; i++) {			printf("%02x", buf[i]);		}		printf("\n");		parcel_grow(&p, msglen);		memcpy(p.data, buf, msglen);		p.size = msglen;		printf("Received %d bytes of data from rild.\n", msglen);		type = parcel_r_int32(&p);		if(type == RESPONSE_SOLICITED) {			interpret_sol_response(&p, fd);		} else {			interpret_unsol_response(&p, fd);		}		free(buf);	}} void dial(struct parcel_t *p, int fd, char *number){	int pktlen, ret;	parcel_w_int32(p, RIL_REQUEST_DIAL);	parcel_w_int32(p, 0);	parcel_w_string(p, number);	parcel_w_int32(p, 0);	parcel_w_int32(p, 0); 	pktlen = htonl(p->size);	ret = write(fd, (void *)&pktlen, sizeof(pktlen));	if(ret < 0) perror("write failed");	ret = write(fd, p->data, p->size);	if(ret < 0) perror("write failed");} void activate_net(struct parcel_t *p, int fd){	int pktlen, ret, i; 	parcel_w_int32(p, RIL_REQUEST_SETUP_DATA_CALL); // request ID	parcel_w_int32(p, 0); // seq number (?)	parcel_w_int32(p, 7); // undocumented magic.	parcel_w_string(p, "1"); // CDMA or GSM. 1 = GSM	parcel_w_string(p, "0"); // data profile. 0 = default	parcel_w_string(p, "wap.cingular"); // APN name	parcel_w_string(p, "WAP@CINGULARGPRS.COM"); // APN user	parcel_w_string(p, "cingular1"); // APN passwd	parcel_w_string(p, "0"); // auth type. 0 usually 	for(i = 0; i < p->size; i++) {		printf("%02x", p->data[i]);	}

Lines 1–500 of 588.