<commit_before>/* Mulator - An extensible {ARM} {e,si}mulator
 * Copyright 2011-2012  <NAME> <<EMAIL>>
 *
 * This file is part of Mulator.
 *
 * Mulator is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Mulator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Mulator.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/prctl.h>

#include "cpu/periph.h"
#include "cpu/core.h"

#include "core/state_sync.h"

struct i2c_instance {
	volatile bool en;
	void (*recv_fn)(uint8_t, uint32_t, char *);
	uint8_t ones;
	uint8_t zeros;
	const char *name;
	const char *host;
	uint16_t port;
	int sock;
	bool is_connected;
	bool is_sending;
	bool is_sending_resp;
	bool is_active_message;
	pthread_t pt;
	pthread_mutex_t pm;
	pthread_cond_t pc;
};

struct i2c_message {
	uint8_t address;
	uint32_t length;
	char *bytes;
};

struct i2c_acknowledge {
	char acked;
};

struct i2c_packet {
	char type;
	union {
		struct i2c_message m;
		struct i2c_acknowledge a;
	};
};

// Caller must hold instance mutex
static int i2c_connect(int sock, const char *host, const uint16_t port) {
	int len;
	struct sockaddr_un address;

	address.sun_family = AF_UNIX;
	strcpy(address.sun_path, host);
	sprintf(address.sun_path+strlen(address.sun_path), ".%d", port);
	len = sizeof(address);

	if (-1 == connect(sock, (struct sockaddr*) &address, len)) {
		WARN("Connecting I2C Bus: %s", strerror(errno));
		return -1;
	}

	char handshake = 'i';
	send(sock, &handshake, 1, 0);
	// XXX: Add timeout
	if (1 != recv(sock, &handshake, 1, 0)) {
		WARN("Connection dropped? %s", strerror(errno));
		return -1;
	}
	if ('i' != handshake) {
		WARN("Bad handshake with software I2C Bus.\n");
		WARN("Expected 'i', Got '%c'\n", handshake);
		return -1;
	}

	return sock;
}

static struct i2c_packet* i2c_recv_packet(int sock) {
	struct i2c_packet* p = malloc(sizeof(struct i2c_packet));

	// XXX: Timeouts
	if (1 != recv(sock, &p->type, 1, 0)) {
		WARN("Bus shutdown. Disconnected\n");
		WARN("Socket reports: %s\n", strerror(errno));
		goto i2c_recv_packet_die;
	}

	if (p->type == 0) {
		// Message
		if (1 != recv(sock, &p->m.address, 1, 0)) {
			WARN("Socket error expecting address\n");
			WARN("Socket reports: %s\n", strerror(errno));
			goto i2c_recv_packet_die;
		}
		if (4 != recv(sock, &p->m.length, 4, MSG_WAITALL)) {
			WARN("Socket error expecting length\n");
			WARN("Socket reports: %s\n", strerror(errno));
			goto i2c_recv_packet_die;
		}
		p->m.length = ntohl(p->m.length);
		p->m.bytes = malloc(p->m.length);
		if (NULL == p->m.bytes) {
			WARN("Failed to allocate memory for I2C packet\n");
			WARN("Message was of length: %d\n", p->m.length);
			WARN("Dropping packet and disconnecting.\n");
			goto i2c_recv_packet_die;
		}
		if (p->m.length != recv(sock, p->m.bytes, p->m.length, MSG_WAITALL)) {
			WARN("Socket error expecting message bytes\n");
			WARN("Socket reports: %s\n", strerror(errno));
			goto i2c_recv_packet_die_with_bytes;
		}
	} else if (p->type == 1) {
		// Acknowledge
		if (1 != recv(sock, &p->a.acked, 1, 0)) {
			WARN("Socket error expecting ACK/NAKE\n");
			WARN("Socket reports: %s\n", strerror(errno));
			goto i2c_recv_packet_die;
		}
	} else {
		WARN("Bad message type %d. Disconnecting\n", p->type);
		goto i2c_recv_packet_die;
	}

	return p;

i2c_recv_packet_die_with_bytes:
	free(p->m.bytes);
i2c_recv_packet_die:
	close(sock);
	free(p);
	return NULL;
}

EXPORT bool i2c_send_message(struct i2c_instance* t,
		uint8_t address, uint32_t length, const char *msg) {
	pthread_mutex_lock(&t->pm);

	if ( ! t->is_connected) {
		WARN("Request to send I2C message, but simulator is not\n");
		WARN("connected to a bus. Trying to connect...\n");
		if (-1 == i2c_connect(t->sock, t->host, t->port)) {
			ERR(E_UNKNOWN, "Could not connect to I2C bus");
		}
		t->is_connected = true;
		pthread_cond_signal(&t->pc);
	}

	t->is_sending = true;<commit_msg>Fix some pretty print issues<commit_after>/* Mulator - An extensible {ARM} {e,si}mulator
 * Copyright 2011-2012  <NAME> <<EMAIL>>
 *
 * This file is part of Mulator.
 *
 * Mulator is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Mulator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Mulator.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/prctl.h>

#include "i2c.h"

#include "cpu/periph.h"
#include "cpu/core.h"

#include "core/state_sync.h"

struct i2c_instance {
	volatile bool en;
	void (*recv_fn)(uint8_t, uint32_t, char *);
	uint8_t ones;
	uint8_t zeros;
	const char *name;
	const char *host;
	uint16_t port;
	int sock;
	bool is_connected;
	bool is_sending;
	bool is_sending_resp;
	bool is_active_message;
	pthread_t pt;
	pthread_mutex_t pm;
	pthread_cond_t pc;
};

struct i2c_message {
	uint8_t address;
	uint32_t length;
	char *bytes;
};

struct i2c_acknowledge {
	char acked;
};

struct i2c_packet {
	char type;
	union {
		struct i2c_message m;
		struct i2c_acknowledge a;
	};
};

// Caller must hold instance mutex
static int i2c_connect(int sock, const char *host, const uint16_t port) {
	int len;
	struct sockaddr_un address;

	address.sun_family = AF_UNIX;
	strcpy(address.sun_path, host);
	sprintf(address.sun_path+strlen(address.sun_path), ".%d", port);
	len = sizeof(address);

	if (-1 == connect(sock, (struct sockaddr*) &address, len)) {
		WARN("Connecting I2C Bus: %s\n", strerror(errno));
		return -1;
	}

	char handshake = 'i';
	send(sock, &handshake, 1, 0);
	// XXX: Add timeout
	if (1 != recv(sock, &handshake, 1, 0)) {
		WARN("Connection dropped? %s\n", strerror(errno));
		return -1;
	}
	if ('i' != handshake) {
		WARN("Bad handshake with software I2C Bus.\n");
		WARN("Expected 'i', Got '%c'\n", handshake);
		return -1;
	}

	return sock;
}

static struct i2c_packet* i2c_recv_packet(int sock) {
	struct i2c_packet* p = malloc(sizeof(struct i2c_packet));

	// XXX: Timeouts
	if (1 != recv(sock, &p->type, 1, 0)) {
		WARN("Bus shutdown. Disconnected\n");
		WARN("Socket reports: %s\n", strerror(errno));
		goto i2c_recv_packet_die;
	}

	if (p->type == 0) {
		// Message
		if (1 != recv(sock, &p->m.address, 1, 0)) {
			WARN("Socket error expecting address\n");
			WARN("Socket reports: %s\n", strerror(errno));
			goto i2c_recv_packet_die;
		}
		if (4 != recv(sock, &p->m.length, 4, MSG_WAITALL)) {
			WARN("Socket error expecting length\n");
			WARN("Socket reports: %s\n", strerror(errno));
			goto i2c_recv_packet_die;
		}
		p->m.length = ntohl(p->m.length);
		p->m.bytes = malloc(p->m.length);
		if (NULL == p->m.bytes) {
			WARN("Failed to allocate memory for I2C packet\n");
			WARN("Message was of length: %d\n", p->m.length);
			WARN("Dropping packet and disconnecting.\n");
			goto i2c_recv_packet_die;
		}
		if (p->m.length != recv(sock, p->m.bytes, p->m.length, MSG_WAITALL)) {
			WARN("Socket error expecting message bytes\n");
			WARN("Socket reports: %s\n", strerror(errno));
			goto i2c_recv_packet_die_with_bytes;
		}
	} else if (p->type == 1) {
		// Acknowledge
		if (1 != recv(sock, &p->a.acked, 1, 0)) {
			WARN("Socket error expecting ACK/NAKE\n");
			WARN("Socket reports: %s\n", strerror(errno));
			goto i2c_recv_packet_die;
		}
	} else {
		WARN("Bad message type %d. Disconnecting\n", p->type);
		goto i2c_recv_packet_die;
	}

	return p;

i2c_recv_packet_die_with_bytes:
	free(p->m.bytes);
i2c_recv_packet_die:
	close(sock);
	free(p);
	return NULL;
}

EXPORT bool i2c_send_message(struct i2c_instance* t,
		uint8_t address, uint32_t length, const char *msg) {
	pthread_mutex_lock(&t->pm);

	if ( ! t->is_connected) {
		WARN("Request to send I2C message, but simulator is not\n");
		WARN("connected to a bus. Trying to connect...\n");
		if (-1 == i2c_connect(t->sock, t->host, t->port)) {
			ERR(E_UNKNOWN, "Could not connect to I2C bus\n");
		}
		t->is_connected = true;
		pthread_cond_signal(&t->pc);
	}

	t->is_sending = true;
{'fraction_non_alphanumeric': 0.1469226425748165, 'fraction_numerical': 0.017052512704686617, 'mean_word_length': 3.9641255605381165, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4595512', 'n_tokens_mistral': 3580, 'n_tokens_neox': 3348, 'n_words': 933}