#include #include #include #include #include #include #include //#include #include "tiny-AES128-C-master/aes.h" #include "../../status.h" #include "../../feeder.h" #define FM4_BUFFER_SIZE 2048 #define AT2000_SAP_ID_ACK 0x00 #define AT2000_SAP_ID_DEVICE_ID 0x01 #define AT2000_SAP_ID_CONF_REQ 0x82 #define AT2000_SAP_ID_CONF_REQ_RES 0x83 #define AT2000_SAP_ID_REMOTE_CONF 0x84 #define AT2000_SAP_ID_FIRMWARE_DATA 0x85 #define AT2000_SAP_ID_IO_ELEMENTS_REQ 0x86 #define AT2000_SAP_ID_IO_ELEMENTS_RES 0x87 #define AT2000_SAP_ID_TRACK_RECORDS_REQ 0x88 #define AT2000_SAP_ID_TRACK_RECORDS_RES 0x89 #define AT2000_SAP_ID_LOG_REQ 0x8A #define AT2000_SAP_ID_LOG_RES 0x8B #define AT2000_SAP_ID_SESSION_END_REQ 0x0C #define AT2000_SAP_ID_FIRWARE_UPDATE_STATUS_REQ 0x8D #define AT2000_SAP_ID_FIRWARE_UPDATE_STATUS_RES 0x8E #define AT2000_SAP_ID_NONE 0xFF #define AT2000_SAP_ID_NO_REQ 0xFF #define AT2000_STATUS_IDLE 0x01 #define AT2000_STATUS_INIT 0x02 #define AT2000_STATUS_TRACK 0x03 #define AT2000_STATUS_TRACK_WAIT 0x04 #define AT2000_STATUS_SESSION_END 0x05 #define AT2000_STATUS_CLOSE 0x06 #define AT2000_IO_EVENTS_COORDINATE_RELIABILITY 11 static uint8_t at2000_aes_key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; //static unsigned char * int_buffer; //static unsigned int int_buffer_pos = 0, int_buffer_pos_wr = 0; //static int imei_flag = 0; //char imei_str[16]; //todo: tohle nejak predavat unsigned char reply_buffer[32]; unsigned int reply_len; //static double values_out[64]; static uint64_t values_sensor[64]; static uint8_t values_type[64]; static time_t values_time; //static uint8_t values_type; static uint8_t values_len; typedef struct unit_t { int fd; char imei[16]; struct unit_t * next; unsigned char * int_buffer; unsigned int int_buffer_pos; unsigned int int_buffer_pos_wr; // unsigned int int_buffer_size; uint8_t IV[16]; uint8_t tstV[16]; uint8_t status; uint8_t sapid; uint32_t data_len; uint8_t pos_obs; } unit_t; static struct unit_t * units; static struct unit_t * aunit; static void (* feederLog)(int priority, const char * fmt, ...); int setLog(void * func) { feederLog = func; return 0; } typedef struct avl_header_t { uint16_t dummy __attribute__ ((packed)); char imei[15]; } avl_header_t; typedef struct at2000_packet_t { // uint8_t codec_id; uint8_t sap; uint8_t len[3]; uint8_t reserv[12]; } __attribute__((packed)) at2000_packet_t; typedef struct at2000_track_t { uint16_t recID; uint8_t reserv[2]; uint32_t timestamp; uint32_t timestamp_frac; float lat; float lon; uint32_t alt; uint32_t speed; uint32_t course; uint32_t geozone_events; uint32_t io_events; uint32_t geozone_val; uint32_t io_val_bits; uint16_t operator; uint16_t ain1; uint16_t ain2; uint16_t ext_power; uint16_t cellid; uint8_t gsm_level; uint8_t current_profile; uint8_t battery_level; uint8_t temperature; uint8_t gps_sats; } __attribute__((packed)) at2000_track_t; uint16_t byteSwap16(uint16_t value) { uint16_t swapped; swapped = (((0x00FF) & (value >> 8)) | ((0xFF00) & (value << 8))); return swapped; } uint32_t byteSwap32(uint32_t value) { uint32_t swapped; swapped = (((0x000000FF) & (value >> 24)) | ((0x0000FF00) & (value >> 8)) | ((0x00FF0000) & (value << 8)) | ((0xFF000000) & (value << 24))); return swapped; } uint64_t byteSwap64(uint64_t value) { uint64_t swapped; swapped = (((0x00000000000000FFULL) & (value >> 56)) | ((0x000000000000FF00ULL) & (value >> 40)) | ((0x0000000000FF0000ULL) & (value >> 24)) | ((0x00000000FF000000ULL) & (value >> 8)) | ((0x000000FF00000000ULL) & (value << 8)) | ((0x0000FF0000000000ULL) & (value << 24)) | ((0x00FF000000000000ULL) & (value << 40)) | ((0xFF00000000000000ULL) & (value << 56))); return swapped; } void arraySwap4(uint8_t * array) { uint8_t temp; temp = array[0]; array[0] = array[3]; array[3] = temp; temp = array[1]; array[1] = array[2]; array[2] = temp; } /* enum states {STATE_IDLE = 0, STATE_DATA_LENGTH, STATE_CODEC_ID, STATE_NO_OF_REC, STATE_TIMESTAMP, STATE_PRIORITY, STATE_LON, STATE_LAT, STATE_ALT, STATE_ANGLE, STATE_SATTS, STATE_SPEED, STATE_EVENT_IO_ID, STATE_TOTAL_IO, STATE_BYTE1_IO, STATE_BYTE1_ID, STATE_BYTE1_VAL, STATE_BYTE2_IO, STATE_BYTE2_ID, STATE_BYTE2_VAL, STATE_BYTE4_IO, STATE_BYTE4_ID, STATE_BYTE4_VAL, STATE_BYTE8_IO, STATE_BYTE8_ID, STATE_BYTE8_VAL, STATE_NO_OF_REC_END, STATE_CRC }; static unsigned char state = STATE_IDLE; //state of status machine, must be global to be accesible by process function when determining if this packet could be imei packet (state is IDLE) */ unsigned char counts[] = { 4, 4, 1, 1, 8, 1, 4, 4, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 4, 1, 1, 8, 1, 4 }; #define PRIO_LOW 0 #define PRIO_HIGHT 1 #define PRIO_PANIC 2 #define PRIO_SECURITY 3 #define VAL_DI1 1 #define VAL_DI2 2 void valuesCopyPos(double lat, double lon, double alt, time_t t, uint8_t type, double * values) { values[0] = lat; values[1] = lon; values[2] = alt; values_time = t; values_type[0] = type; values_type[1] = type; values_type[2] = type; } //todo: nasledujici dve pole do pole struktur, tedy vcetne multiplu /* {FM4 type, FEEDER sensor type id, sensor id, alertable (if prio is 1(high))} */ uint8_t sensorTypes[][4] = { {1, TYPE_PERCENTAGE, 2, 0}, {9, TYPE_ANALOG_INPUT, 7, 0}, {21, TYPE_SIGNAL_STRENGTH, 7, 0}, {22, TYPE_PROFILE, 1, 0}, {53, TYPE_DIGITAL_INPUT, 14, 0}, {72, TYPE_THERMOMETER, 28, 0}, {101, TYPE_DIGITAL_INPUT, 15, 0}, {102, TYPE_DIGITAL_INPUT, 15, 0}, {103, TYPE_RESISTANCE, 1, 0}, {200, TYPE_LINK, 8, 0}, {210, TYPE_SPEED, 8, 0}, {238, TYPE_DIGITAL_INPUT, 17, 0}, {239, TYPE_LINK, 9, 0}, {240, TYPE_MOVE, 2, 0}, {0, 0, 0, 0} }; /* uint8_t sensorTypes[][4] = { {1, TYPE_DIGITAL_INPUT, 5, 0}, {2, TYPE_DIGITAL_INPUT, 6, 1}, {3, TYPE_DIGITAL_INPUT, 7, 0}, {4, TYPE_DIGITAL_INPUT, 8, 0}, {9, TYPE_ANALOG_INPUT, 1, 0}, {10, TYPE_ANALOG_INPUT, 2, 0}, {11, TYPE_ANALOG_INPUT, 3, 0}, {19, TYPE_ANALOG_INPUT, 4, 0}, {21, TYPE_SIGNAL_STRENGTH, 3, 0}, {24, TYPE_SPEED, 2, 0}, {66, TYPE_VOLTAGE, 11, 0}, {67, TYPE_VOLTAGE, 10, 0}, {68, TYPE_CURRENT, 2, 0}, {69, TYPE_SIGNAL_STRENGTH, 4, 0}, {70, TYPE_THERMOMETER, 11, 0}, {72, TYPE_THERMOMETER, 12, 0}, {73, TYPE_THERMOMETER, 13, 0}, {74, TYPE_THERMOMETER, 14, 0}, {79, TYPE_ACCELERATION, 2, 0}, {80, TYPE_SPEED, 3, 0}, {81, TYPE_CRUISE, 1, 0}, {82, TYPE_CRUISE, 2, 0}, {83, TYPE_CRUISE, 3, 0}, {84, TYPE_ENGINE, 1, 0}, {85, TYPE_ENGINE, 2, 0}, {86, TYPE_ENGINE, 3, 0}, {87, TYPE_LEVEL, 4, 0}, {88, TYPE_FREQUENCY, 1, 0}, {104, TYPE_TIME, 1, 0}, {127, TYPE_TEMP, 20, 0}, {128, TYPE_TEMP, 21, 0}, {135, TYPE_FLOW, 6, 0}, {136, TYPE_FLOW, 7, 0}, {207, TYPE_ID, 1, 0}, {249, TYPE_SIGNAL_STRENGTH, 5, 0}, {0, 0, 0, 0} }; */ double sensorMulti[] = { 1.0, 1.0, 1.0, 1.0, 1.0, 0.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, }; /* double sensorMulti[] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.001, 0.001, 0.001, 1.0, 0.1, 0.1, 0.1, 0.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; */ int getSensorType(uint8_t sensor) { int i; i = 0; while (sensorTypes[i][0] != 0) { if (sensorTypes[i][0] == sensor) return i; i++; } return -1; } void valuesCopyVal(double value, uint8_t sensor, time_t t, uint8_t type, double * values) { uint8_t sensor_index; sensor_index = getSensorType(sensor); //todo: check return value values[values_len] = value * sensorMulti[sensor_index]; values_sensor[values_len] = sensorTypes[sensor_index][2] * 10000 + sensorTypes[sensor_index][1] * 10000000; values_time = t; if ((type == VALUES_TYPE_ALERT) && (sensorTypes[sensor_index][3] == 1)) values_type[values_len] = VALUES_TYPE_ALERT; else values_type[values_len] = VALUES_TYPE_OBS; feederLog(LOG_DEBUG, "fm4: Observation type %s\n", (values_type[values_len] == VALUES_TYPE_ALERT) ? "alert" : "obs"); values_len++; } //---------------------------------------------------------------------------------------------- struct unit_t * unitFind(int fd) { struct unit_t * unit; unit = units; while (unit != NULL) { if (unit->fd == fd) { return unit; } unit = unit->next; } return NULL; } struct unit_t * unitCreate(int fd) { struct unit_t * unit, * unit_new; unit_new = malloc(sizeof(struct unit_t)); if (unit_new == NULL) return NULL; unit_new->fd = fd; unit_new->imei[0] = 0; unit_new->next = NULL; unit_new->int_buffer = malloc(FM4_BUFFER_SIZE); if (unit_new->int_buffer == NULL) { free(unit_new); return NULL; } // unit_new->int_buffer_size = FM4_BUFFER_SIZE; unit_new->int_buffer_pos = 0; unit_new->int_buffer_pos_wr = 0; unit_new->status = AT2000_STATUS_IDLE; unit_new->sapid = AT2000_SAP_ID_NONE; if (units == NULL) units = unit_new; else { unit = units; while (unit->next != NULL) { unit = unit->next; } unit->next = unit_new; } return unit_new; } int imei(struct unit_t * unit, unsigned char * data) { char imei_str[16]; memcpy(imei_str, data, 15); imei_str[15] = 0; feederLog(LOG_DEBUG, "at2000: Imei is %s\n", imei_str); strcpy(unit->imei, imei_str); return 1; } int init(void * param) { param = param; bzero(reply_buffer, 32); reply_len = 0; units = aunit = NULL; return 0; } void logHex(char * buffer, unsigned char * data, unsigned int length) { unsigned int i; buffer[0] = 0; for (i = 0; i < length; i++) { sprintf(buffer + strlen(buffer), "%02X ", data[i]); } } unsigned int process(void *lib_data, int socket, unsigned char *data, unsigned int length, unsigned long long int *id, time_t * tm, double *result_array, uint64_t * sensors, unsigned int *type) { unsigned int ret = 0; struct unit_t * unit; char buffer[32768]; unsigned int l; struct at2000_packet_t * packet; uint8_t buffer_dec[512]; (void)lib_data; if (data != NULL) { feederLog(LOG_DEBUG, "at2000: Incoming data: len %d: \n", length); l = length; while (l > 0) { logHex(buffer, data + length - l, (l > 16) ? 16:l); feederLog(LOG_DEBUG, "%s\n", buffer); l -= (l > 16) ? 16:l; } } unit = unitFind(socket); if (unit == NULL) { feederLog(LOG_DEBUG, "at2000: new unit for socket %d\n", socket); unit = unitCreate(socket); //todo: check if scucsefull } else { feederLog(LOG_DEBUG, "at2000: data from known unit on socket %d\n", socket); } aunit = unit; if (aunit->status == AT2000_STATUS_IDLE) { if (data[0] == 1) { packet = (struct at2000_packet_t *)(data + 1); aunit->data_len = ((uint32_t)(packet->len[0])) + ((uint32_t)(packet->len[1]) << 8) + ((uint32_t)(packet->len[2]) << 16); feederLog(LOG_DEBUG, "at2000: data size %d\n", aunit->data_len); if (packet->sap == AT2000_SAP_ID_DEVICE_ID) { imei(aunit, data + 1 + sizeof(struct at2000_packet_t)); memcpy(aunit->IV, data + 1 + sizeof(struct at2000_packet_t) + 15, 16); memcpy(aunit->tstV, data + 1 + sizeof(struct at2000_packet_t) + 15 + 16, 16); feederLog(LOG_DEBUG, "at2000: tstV decrypt\n"); AES128_CBC_decrypt_buffer(buffer_dec, aunit->tstV, 16, at2000_aes_key, aunit->IV); logHex(buffer, buffer_dec, 16); feederLog(LOG_DEBUG, "%s\n", buffer); if (((aunit->imei[14] ^ aunit->IV[0]) != buffer_dec[0]) || ((aunit->imei[13] ^ aunit->IV[1]) != buffer_dec[1]) || ((aunit->imei[12] ^ aunit->IV[2]) != buffer_dec[2]) || ((aunit->imei[11] ^ aunit->IV[3]) != buffer_dec[3])) { feederLog(LOG_ERR, "at2000: tstV not passed\n"); ret = -1; } } } else { feederLog(LOG_ERR, "at2000: bad codec id\n"); ret = -1; } } else { if (data != NULL) { aunit->pos_obs = VALUES_TYPE_POS; if (aunit->sapid == AT2000_SAP_ID_NONE) { packet = (struct at2000_packet_t *)(data); aunit->data_len = ((uint32_t)(packet->len[0])) + ((uint32_t)(packet->len[1]) << 8) + ((uint32_t)(packet->len[2]) << 16); feederLog(LOG_DEBUG, "at2000: data size %d\n", aunit->data_len); if (packet->sap == AT2000_SAP_ID_TRACK_RECORDS_RES) { feederLog(LOG_DEBUG, "at2000: track log in\n"); aunit->sapid = packet->sap; /* if (data_len < aunit->int_buffer_size) { aunit->int_buffer = realloc(aunit->int_buffer, data_len); if (aunit->int_buffer == NULL) { feederLog(LOG_ERR, "at2000: no more memory for buffer\n");//todo: puvodni pamet je uvolnena nebo jen zustava nerealokovana? unit->int_buffer_pos_wr = unit->int_buffer_pos = unit->int_buffer_size = 0; ret = -1; return ret; } } */ // memcpy(aunit->int_buffer + aunit->int_buffer_pos_wr, data + 16, length - 16); memcpy(data, aunit->tstV, 16); AES128_CBC_decrypt_buffer(aunit->int_buffer + aunit->int_buffer_pos_wr, data, length, at2000_aes_key, aunit->IV); aunit->int_buffer_pos_wr += (length); aunit->int_buffer_pos = 16; /* AES128_CBC_decrypt_buffer(aunit->int_buffer + aunit->int_buffer_pos_wr, data + 16, length - 16, at2000_aes_key, aunit->IV); aunit->int_buffer_pos_wr += (length - 16);*/ } } else if (aunit->sapid == AT2000_SAP_ID_TRACK_RECORDS_RES) { AES128_CBC_decrypt_buffer(aunit->int_buffer + aunit->int_buffer_pos_wr, data, length, at2000_aes_key, aunit->IV); aunit->int_buffer_pos_wr += (length); } } if (aunit->sapid == AT2000_SAP_ID_TRACK_RECORDS_RES) { //while (aunit->int_buffer_pos + sizeof(struct at2000_track_t) <= aunit->int_buffer_pos_wr) if (aunit->int_buffer_pos + sizeof(struct at2000_track_t) <= aunit->int_buffer_pos_wr) { //AES128_CBC_decrypt_buffer(buffer_dec, aunit->int_buffer + aunit->int_buffer_pos, sizeof(struct at2000_track_t), at2000_aes_key, aunit->IV); struct at2000_track_t * track; track = (struct at2000_track_t *)(aunit->int_buffer + aunit->int_buffer_pos); switch (aunit->pos_obs) { case VALUES_TYPE_POS: { logHex(buffer, aunit->int_buffer + aunit->int_buffer_pos, sizeof(struct at2000_track_t)); feederLog(LOG_DEBUG, "%s\n", buffer); /* feederLog(LOG_DEBUG, "track id %d\n", track->recID); feederLog(LOG_DEBUG, "timestamp %ld\n", track->timestamp); feederLog(LOG_DEBUG, "track lat %f\n", (float)track->lat); feederLog(LOG_DEBUG, "track lon %f\n", (float)track->lon); */ result_array[0] = (float)track->lat; result_array[1] = (float)track->lon; sensors[0] = sensors[1] = 0x10; *type = VALUES_TYPE_POS; *id = atol(aunit->imei); *tm = track->timestamp; if ((track->gps_sats != 0xFF) && ((float)track->lat != 0.0) && ((float)track->lon != 0.0) && ((track->io_events & (1 << AT2000_IO_EVENTS_COORDINATE_RELIABILITY)) != 0)) { ret = 2; aunit->pos_obs = VALUES_TYPE_OBS; } else { feederLog(LOG_DEBUG, "at2000: invalid fix\n"); ret = 0; aunit->int_buffer_pos += sizeof(struct at2000_track_t); aunit->data_len -= sizeof(struct at2000_track_t); } break; } case VALUES_TYPE_OBS: { result_array[0] = (float)track->battery_level; sensors[0] = 540070000; *type = VALUES_TYPE_OBS; *id = atol(aunit->imei); *tm = track->timestamp; ret = 1; aunit->pos_obs = VALUES_TYPE_POS; aunit->int_buffer_pos += sizeof(struct at2000_track_t); aunit->data_len -= sizeof(struct at2000_track_t); break; } } } else { memcpy(aunit->int_buffer, aunit->int_buffer + aunit->int_buffer_pos, aunit->int_buffer_pos_wr - aunit->int_buffer_pos); aunit->int_buffer_pos_wr = aunit->int_buffer_pos_wr - aunit->int_buffer_pos; aunit->int_buffer_pos = 0; } } } return ret; } void replyBuild(uint8_t * buffer, uint8_t id, uint8_t * payload, uint8_t payload_len) { struct at2000_packet_t * packet; packet = (at2000_packet_t *)buffer; bzero(buffer, 32); packet->sap = id; packet->len[0] = payload_len; packet->len[1] = packet->len[2] = 0; if ((payload != NULL) && (payload_len > 0)) memcpy(packet->reserv, payload, payload_len); } void __sleep__(unsigned int sec) { struct timespec tv; tv.tv_sec = sec; tv.tv_nsec = 0; while (nanosleep(&tv, &tv) == -1) ; } int reply(void *lib_data, int socket, unsigned char *data) { unsigned int temp_reply_len = 0; uint8_t payload[16]; (void)lib_data; (void)socket; feederLog(LOG_DEBUG, "at2000: replying\n"); if (aunit->status == AT2000_STATUS_IDLE) { __sleep__(1); payload[0] = 0x00; replyBuild(data, AT2000_SAP_ID_ACK, payload, 1); temp_reply_len = 32; aunit->status = AT2000_STATUS_INIT; } else if (aunit->status == AT2000_STATUS_INIT) { __sleep__(1); replyBuild(data, AT2000_SAP_ID_TRACK_RECORDS_REQ, NULL, 0); temp_reply_len = 16; aunit->status = AT2000_STATUS_TRACK_WAIT; } else if (aunit->status == AT2000_STATUS_TRACK) { __sleep__(1); payload[0] = 0x00; replyBuild(data, AT2000_SAP_ID_ACK, payload, 1); temp_reply_len = 32; if (aunit->data_len == 0) aunit->status = AT2000_STATUS_SESSION_END; else aunit->status = AT2000_STATUS_TRACK_WAIT; } else if (aunit->status == AT2000_STATUS_TRACK_WAIT) { temp_reply_len = 0; aunit->status = AT2000_STATUS_TRACK; } else if (aunit->status == AT2000_STATUS_SESSION_END) { __sleep__(1); replyBuild(data, AT2000_SAP_ID_SESSION_END_REQ, NULL, 0); temp_reply_len = 16; aunit->status = AT2000_STATUS_CLOSE; } else if (aunit->status == AT2000_STATUS_CLOSE) { __sleep__(1); temp_reply_len = -1; } /* memcpy(data, reply_buffer, reply_len); temp_reply_len = reply_len; reply_len = 0; */ return temp_reply_len; } int open(void *lib_data, int socket) { (void)lib_data; (void)socket; feederLog(LOG_DEBUG, "at2000: socket %d opened\n", socket); return 0; } int close(void *lib_data, int socket) { struct unit_t * unit, * unit_parent; (void)lib_data; (void)socket; feederLog(LOG_DEBUG, "at2000: socket %d closed\n", socket); unit = unitFind(socket); if (unit != NULL) { free(unit->int_buffer); unit->imei[0] = 0; //todo: nebo mozna lepe, zrusit celou jednotku - coz bacha na next unit->fd = -1; if (unit == units) units = unit->next; for (unit_parent = units; (unit_parent != NULL); unit_parent = unit_parent->next) { if (unit_parent->next == unit) { unit_parent->next = unit->next; } } free(unit); unit = NULL; } // unit->int_buffer_pos_wr = unit->int_buffer_pos = unit->int_buffer_size = 0; // unit->int_buffer_pos_wr = unit->int_buffer_pos = 0; return 0; }