<commit_before>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <hidapi.h>
#include <stdbool.h>

#define DATA_MAX_LENGTH 256

static unsigned char parse_print_buf(unsigned char* data, int len)
{
	// The TEMPers' keyboard interface uses numbered reports, so the first byte
	// is the report ID, then comes the report data.
	// In the report data, the first byte is the modifier bitmask, the second
	// is reserved (probably all zero), then there's 5 byte of pressed keys.
	// For the TEMPers, I've only ever seen one key at a time being pressed.
	
	if ( len < 2 ) return 0;
	// Ignore key releases.
	bool all_zero = ( data[1] == 0 );
	for ( int i = 3 ; all_zero && i < len ; i++ )
	{
		if ( data[i] != 0 )
		{
			all_zero = false;
			break;
		}
	}
	if ( all_zero )
	{
		return 0;
	}
	// Print all pressed keys
	printf("(");
	// Starting with the modifiers
	if ( data[1] & 0x01 ) printf("C"); if ( data[1] & 0x10 ) printf("c");
	if ( data[1] & 0x02 ) printf("S"); if ( data[1] & 0x20 ) printf("s");
	if ( data[1] & 0x04 ) printf("A"); if ( data[1] & 0x40 ) printf("a");
	if ( data[1] & 0x08 ) printf("W"); if ( data[1] & 0x80 ) printf("w");
	// Then the pressed keys (if any)
	unsigned char last = 0;
	bool first = ( data[1] == 0 );
	for ( int i = 3 ; i < len ; i++ )
	{
		if ( data[i] != 0 )
		{
			last = data[i];
			printf("%s%.2x", first ? "" : " ", data[i]);
			first = false;
		}
	}
	printf(")%s", last == 0x28 ? "\n" : " ");
	fflush(stdout);
	return last;
}

static int start_device(hid_device* dev, unsigned char* last)
{
	unsigned char trigger_data[2] = { 0, 0 };
	unsigned char read_data[DATA_MAX_LENGTH] = { 0 };
	printf("Starting device");
	for ( int write_count = 0; write_count < 100; write_count++ )
	{
		int size = hid_write(dev, trigger_data, sizeof(trigger_data));
		if ( size <= 0 )
		{
			printf("\n");
			fprintf(stderr, "Write to device failed: %ls\n", hid_error(dev));
			return 5;
		}
		printf(".");
		fflush(stdout);
		
		size = hid_read_timeout(dev, read_data, DATA_MAX_LENGTH, 0);
		if ( size < 0 )
		{
			printf("\n");
			fprintf(stderr, "Read from device failed: %ls\n", hid_error(dev));
			return 6;
		}
		else if ( size > 0 )
		{
			// TODO: check if this was a device stop rather than start
			printf(" Device started after %i writes.\n", write_count + 1);
			if ( size == DATA_MAX_LENGTH )
			{
				fprintf(
					stderr,
					"Warning: data buffer full, may have lost some data.\n\n"
				);
			}
			*last = parse_print_buf(read_data, size);
			
			return 0;
		}
		// else, size == 0, which means timeout, which means keep going.
	}
	printf("\n");
	fprintf(stderr, "Device failed to start, giving up.\n");
	return 4;
}

static int read_device(hid_device* dev, long read_count, unsigned char* last)
{
	unsigned char read_data[DATA_MAX_LENGTH] = { 0 };
	int timeout = 10000;
	for ( int cur_count = 0 ; cur_count < read_count ; )
	{
		int size = hid_read_timeout(dev, read_data, DATA_MAX_LENGTH, timeout);
		if ( size < 0 )
		{
			fprintf(stderr, "Read from device failed: %ls\n", hid_error(dev));
			return 6;
		}
		else if ( size == 0 )
		{
			fprintf(stderr, "Read from device timed out.\n");
			return 7;
		}
		else<commit_msg>Added a check for if the start actually stopped the device, and retrying.<commit_after>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <hidapi.h>
#include <stdbool.h>

#define DATA_MAX_LENGTH 256

static unsigned char parse_print_buf(unsigned char* data, int len)
{
	// The TEMPers' keyboard interface uses numbered reports, so the first byte
	// is the report ID, then comes the report data.
	// In the report data, the first byte is the modifier bitmask, the second
	// is reserved (probably all zero), then there's 5 byte of pressed keys.
	// For the TEMPers, I've only ever seen one key at a time being pressed.
	
	if ( len < 2 ) return 0;
	// Ignore key releases.
	bool all_zero = ( data[1] == 0 );
	for ( int i = 3 ; all_zero && i < len ; i++ )
	{
		if ( data[i] != 0 )
		{
			all_zero = false;
			break;
		}
	}
	if ( all_zero )
	{
		return 0;
	}
	// Print all pressed keys
	printf("(");
	// Starting with the modifiers
	if ( data[1] & 0x01 ) printf("C"); if ( data[1] & 0x10 ) printf("c");
	if ( data[1] & 0x02 ) printf("S"); if ( data[1] & 0x20 ) printf("s");
	if ( data[1] & 0x04 ) printf("A"); if ( data[1] & 0x40 ) printf("a");
	if ( data[1] & 0x08 ) printf("W"); if ( data[1] & 0x80 ) printf("w");
	// Then the pressed keys (if any)
	unsigned char last = 0;
	bool first = ( data[1] == 0 );
	for ( int i = 3 ; i < len ; i++ )
	{
		if ( data[i] != 0 )
		{
			last = data[i];
			printf("%s%.2x", first ? "" : " ", data[i]);
			first = false;
		}
	}
	printf(")%s", last == 0x28 ? "\n" : " ");
	fflush(stdout);
	return last;
}

static int start_device(hid_device* dev, unsigned char* last)
{
	unsigned char trigger_data[2] = { 0, 0 };
	unsigned char read_data[DATA_MAX_LENGTH] = { 0 };
	printf("Starting device");
	int attempts = 5;
	for ( int write_count = 0; attempts > 0 && write_count < 100; write_count++ )
	{
		int size = hid_write(dev, trigger_data, sizeof(trigger_data));
		if ( size <= 0 )
		{
			printf("\n");
			fprintf(stderr, "Write to device failed: %ls\n", hid_error(dev));
			return 5;
		}
		printf(".");
		fflush(stdout);
		
		size = hid_read_timeout(dev, read_data, DATA_MAX_LENGTH, 0);
		if ( size < 0 )
		{
			printf("\n");
			fprintf(stderr, "Read from device failed: %ls\n", hid_error(dev));
			return 6;
		}
		else if ( size > 0 )
		{
			*last = parse_print_buf(read_data, size);
			if ( size == DATA_MAX_LENGTH )
			{
				fprintf(
					stderr,
					"Warning: data buffer full, may have lost some data.\n\n"
				);
			}
			if ( *last == 0x28 )
			{
				do
				{
					// Was this a stop? See if we're getting more data immediately.
					size = hid_read_timeout(dev, read_data, DATA_MAX_LENGTH, 100);
					if ( size == DATA_MAX_LENGTH )
					{
						fprintf(
							stderr,
							"Warning: data buffer full, may have lost some data.\n\n"
						);
					}
					if ( size < 0 )
					{
						fprintf(stderr, "Read from device failed: %ls\n", hid_error(dev));
						return 6;
					}
					else if ( size > 0 )
					{
						*last = parse_print_buf(read_data, size);
					}
				} while ( size > 0 && *last == 0 );
				
				if ( size == 0 )
				{
					// Timeout
					printf(
						"Device responded with stop after %i writes.\n",
						write_count + 1
					);
					printf("Trying again");
					fflush(stdout);
					write_count = 0;
					attempts--;
					continue;
				}
			}
			printf("Device started after %i writes.\n", write_count + 1);
			return 0;
		}
		// else, size == 0, which means timeout, which means keep going.
	}
	printf("\n");
	fprintf(stderr, "Device failed to start, giving up.\n");
	return 4;
}

static int read_device(hid_device* dev, long read_count, unsigned char* last)
{
	unsigned char read_data[DATA_MAX_LENGTH] = { 0 };
	int timeout = 10000;
	for ( int cur_count = 0 ; cur_count < read_count ; )
	{
		int size = hid_read_timeout(dev, read_data, DATA_MAX_LENGTH, timeout);
		if ( size < 0 )
		{
			fprintf(stderr, "Read from device failed: %ls\n", hid_error(dev));
			return 6;
		}
		else if ( size == 0 )
		{
			fprintf(stderr, "Read from device timed out.\n");
			return 7;
		}
		else
{'fraction_non_alphanumeric': 0.15384615384615385, 'fraction_numerical': 0.02462645268400664, 'mean_word_length': 2.8823845327604727, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '7264853', 'n_tokens_mistral': 3102, 'n_tokens_neox': 2626, 'n_words': 817}