Exemple #1
0
int		ft_unsetenv(const char *var)
{
	char	**ep;
	char	**sp;
	int		len;

	if (var == NULL || var[0] == '\0' || ft_strchr(var, '=') != NULL)
	{
		erro_msg("Invalid argument(s)", NULL);
		return (-1);
	}
	len = ft_strlen(var);
	ep = environ;
	while (ep != NULL)
	{
		if (ft_strncmp((const char *)ep, var, len) == 0 && (*ep)[len] == '=')
		{
			sp = ep;
			while (*sp != NULL)
			{
				*sp = *(sp + 1);
				sp++;
			}
		}
		else
			ep++;	
	}
	return (0);
}
Exemple #2
0
uint8_t I2C_TxBufferPop()
{
	// Return 0xFF if no buffer left (do not rely on this)
	if ( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) >= I2C_TxBuffer.size )
	{
		erro_msg("No buffer to pop an entry from... ");
		printHex( I2C_TxBuffer.head );
		print(" ");
		printHex( I2C_TxBuffer.tail );
		print(" ");
		printHex( I2C_TxBuffer.sequencePos );
		print(NL);
		return 0xFF;
	}

	// If there is currently no sequence being sent, the first entry in the RingBuffer is the length
	if ( I2C_TxBuffer.sequencePos == 0 )
	{
		I2C_TxBuffer.sequencePos = 0xFF; // So this doesn't become an infinite loop
		I2C_RxBuffer.sequencePos = I2C_TxBufferPop();
		I2C_TxBuffer.sequencePos = I2C_TxBufferPop();
	}

	uint8_t data = I2C_TxBuffer.buffer[ I2C_TxBuffer.head ];

	// Prune head
	I2C_TxBuffer.head++;

	// Wrap-around case
	if ( I2C_TxBuffer.head >= I2C_TxBuffer.size )
		I2C_TxBuffer.head = 0;

	// Decrement buffer sequence (until next stop will be sent)
	I2C_TxBuffer.sequencePos--;

	/*
	dbug_msg("Popping: ");
	printHex( data );
	print(" ");
	printHex( I2C_TxBuffer.head );
	print(" ");
	printHex( I2C_TxBuffer.tail );
	print(" ");
	printHex( I2C_TxBuffer.sequencePos );
	print(NL);
	*/
	return data;
}
Exemple #3
0
void Connect_addBytes( uint8_t *buffer, uint8_t count, uint8_t uart )
{
	// Too big to fit into buffer
	if ( count > UART_Buffer_Size )
	{
		erro_msg("Too big of a command to fit into the buffer...");
		return;
	}

	// Invalid UART
	if ( uart >= UART_Num_Interfaces )
	{
		erro_print("Invalid UART to send from...");
		return;
	}

	// Delay UART copy until there's some space left
	while ( uart_tx_buf[ uart ].items + count > UART_Buffer_Size )
	{
		warn_msg("Too much data to send on UART");
		printInt8( uart );
		print( ", waiting..." NL );
		delay_ms( 1 );
		// FIXME Buffer will not drain here....
	}

	// Append data to ring buffer
	for ( uint8_t c = 0; c < count; c++ )
	{
		if ( Connect_debug )
		{
			printHex( buffer[ c ] );
			print(" +");
			printInt8( uart );
			print( NL );
		}

		uart_tx_buf[ uart ].buffer[ uart_tx_buf[ uart ].tail++ ] = buffer[ c ];
		uart_tx_buf[ uart ].items++;
		if ( uart_tx_buf[ uart ].tail >= UART_Buffer_Size )
			uart_tx_buf[ uart ].tail = 0;
		if ( uart_tx_buf[ uart ].head == uart_tx_buf[ uart ].tail )
			uart_tx_buf[ uart ].head++;
		if ( uart_tx_buf[ uart ].head >= UART_Buffer_Size )
			uart_tx_buf[ uart ].head = 0;
	}
}
Exemple #4
0
int		ft_setenv(const char *key, const char *val, int overwrite)
{
	char	*es;

	if (key == NULL || key[0] == '\0' || ft_strchr(key, '=') != NULL)
	{
		erro_msg("Invalid argument(s)", NULL);
		return (-1);
	}
	if (getenv(key) != NULL && overwrite == 0)
		return (0);
	ft_unsetenv(key);
	if (!(es = (char *)malloc(ft_strlen(key) + ft_strlen(val) + 2)))
		return (-1);
	ft_strjoin(ft_strjoin(ft_strcpy(es, key), "="), val);
	if (!putenv(es))
		return (-1);
	return (1);
}
void Connect_rx_process( uint8_t uartNum )
{
	// Determine current position to read until
	uint16_t bufpos = 0;
	switch ( uartNum )
	{
	DMA_BUF_POS( 0, bufpos );
	DMA_BUF_POS( 1, bufpos );
	}

	// Process each of the new bytes
	// Even if we receive more bytes during processing, wait until the next check so we don't starve other tasks
	while ( bufpos != uart_rx_buf[ uartNum ].last_read )
	{
		// If the last_read byte is at the buffer edge, roll back to beginning
		if ( uart_rx_buf[ uartNum ].last_read == 0 )
		{
			uart_rx_buf[ uartNum ].last_read = UART_Buffer_Size;

			// Check to see if we're at the boundary
			if ( bufpos == UART_Buffer_Size )
				break;
		}

		// Read the byte out of Rx DMA buffer
		uint8_t byte = uart_rx_buf[ uartNum ].buffer[ UART_Buffer_Size - uart_rx_buf[ uartNum ].last_read-- ];

		if ( Connect_debug )
		{
			printHex( byte );
			print(" ");
		}

		// Process UART byte
		switch ( uart_rx_status[ uartNum ].status )
		{
		// Every packet must start with a SYN / 0x16
		case UARTStatus_Wait:
			if ( Connect_debug )
			{
				print(" Wait ");
			}
			uart_rx_status[ uartNum ].status = byte == 0x16 ? UARTStatus_SYN : UARTStatus_Wait;
			break;

		// After a SYN, there must be a SOH / 0x01
		case UARTStatus_SYN:
			if ( Connect_debug )
			{
				print(" SYN ");
			}
			uart_rx_status[ uartNum ].status = byte == 0x01 ? UARTStatus_SOH : UARTStatus_Wait;
			break;

		// After a SOH the packet structure may diverge a bit
		// This is the packet type field (refer to the Command enum)
		// For very small packets (e.g. IdRequest) this is all that's required to take action
		case UARTStatus_SOH:
		{
			if ( Connect_debug )
			{
				print(" SOH ");
			}

			// Check if this is actually a reserved CMD 0x16 (Error condition)
			if ( byte == Command_SYN )
			{
				uart_rx_status[ uartNum ].status = UARTStatus_SYN;
				break;
			}

			// Otherwise process the command
			if ( byte < Command_TOP )
			{
				uart_rx_status[ uartNum ].status = UARTStatus_Command;
				uart_rx_status[ uartNum ].command = byte;
				uart_rx_status[ uartNum ].bytes_waiting = 0xFFFF;
			}
			// Invalid packet type, ignore
			else
			{
				uart_rx_status[ uartNum ].status = UARTStatus_Wait;
			}

			// Check if this is a very short packet
			switch ( uart_rx_status[ uartNum ].command )
			{
			case IdRequest:
				Connect_receive_IdRequest( 0, (uint16_t*)&uart_rx_status[ uartNum ].bytes_waiting, uartNum );
				uart_rx_status[ uartNum ].status = UARTStatus_Wait;
				break;

			default:
				if ( Connect_debug )
				{
					print(" ### ");
					printHex( uart_rx_status[ uartNum ].command );
				}
				break;
			}
			break;
		}

		// After the packet type has been deciphered do Command specific processing
		// Until the Command has received all the bytes it requires the UART buffer stays in this state
		case UARTStatus_Command:
		{
			if ( Connect_debug )
			{
				print(" CMD ");
			}
			/* Call specific UARTConnect command receive function */
			uint8_t (*rcvFunc)(uint8_t, uint16_t(*), uint8_t) = (uint8_t(*)(uint8_t, uint16_t(*), uint8_t))(Connect_receiveFunctions[ uart_rx_status[ uartNum ].command ]);
			if ( rcvFunc( byte, (uint16_t*)&uart_rx_status[ uartNum ].bytes_waiting, uartNum ) )
				uart_rx_status[ uartNum ].status = UARTStatus_Wait;
			break;
		}

		// Unknown status, should never get here
		default:
			erro_msg("Invalid UARTStatus...");
			uart_rx_status[ uartNum ].status = UARTStatus_Wait;
			continue;
		}

		if ( Connect_debug )
		{
			print( NL );
		}
	}
}
Exemple #6
0
// Macro Processing Loop, called from the periodic execution thread
// Called once per USB buffer send
void Macro_periodic()
{
	// Latency measurement
	Latency_start_time( macroLatencyResource );

#if defined(ConnectEnabled_define)
	// Only compile in if a Connect node module is available
	// If this is a interconnect slave node, send all scancodes to master node
	if ( !Connect_master )
	{
		if ( macroTriggerEventBufferSize > 0 )
		{
			Connect_send_ScanCode( Connect_id, macroTriggerEventBuffer, macroTriggerEventBufferSize );
			macroTriggerEventBufferSize = 0;
		}
		return;
	}
#endif

#if defined(ConnectEnabled_define) || defined(PressReleaseCache_define)
#if defined(ConnectEnabled_define)
	// Check if there are any ScanCodes in the interconnect cache to process
	if ( Connect_master && macroInterconnectCacheSize > 0 )
#endif
	{
		// Iterate over all the cache ScanCodes
		uint8_t currentInterconnectCacheSize = macroInterconnectCacheSize;
		macroInterconnectCacheSize = 0;
		for ( uint8_t c = 0; c < currentInterconnectCacheSize; c++ )
		{
			// Add to the trigger list
			macroTriggerEventBuffer[ macroTriggerEventBufferSize++ ] = macroInterconnectCache[ c ];

			// TODO Handle other TriggerGuide types (e.g. analog)
			switch ( macroInterconnectCache[ c ].type )
			{
			// Normal (Press/Hold/Release)
			case TriggerType_Switch1:
			case TriggerType_Switch2:
			case TriggerType_Switch3:
			case TriggerType_Switch4:
			case TriggerType_LED1:
				// Decide what to do based on the current state
				switch ( macroInterconnectCache[ c ].state )
				{
				// Re-add to interconnect cache in hold state
				case ScheduleType_P: // Press
				//case ScheduleType_H: // Hold // XXX Why does this not work? -HaaTa
					macroInterconnectCache[ c ].state = ScheduleType_H;
					macroInterconnectCache[ macroInterconnectCacheSize++ ] = macroInterconnectCache[ c ];
					break;

				case ScheduleType_R: // Release
					break;

				// Otherwise, do not re-add
				default:
					break;
				}
				break;

			// Not implemented
			default:
				erro_msg("Interconnect Trigger Event Type - Not Implemented ");
				printInt8( macroInterconnectCache[ c ].type );
				print( NL );
				break;
			}
		}
	}
#endif
	// Macro incoming state debug
	switch ( macroDebugMode )
	{
	case 1:
	case 2:
		// Iterate over incoming triggers
		for ( uint16_t trigger = 0; trigger < macroTriggerEventBufferSize; trigger++ )
		{
			// Show debug info about incoming trigger
			Macro_showTriggerEvent( &macroTriggerEventBuffer[trigger] );
			print( NL );
		}

	case 3:
	default:
		break;
	}

	// Check macroTriggerEventBufferSize to make sure no overflow
	if ( macroTriggerEventBufferSize >= MaxScanCode_KLL )
	{
		// No scancodes defined
		if ( MaxScanCode_KLL == 0 )
		{
			warn_print("No scancodes defined! Check your BaseMap!");
		}
		// Bug!
		else
		{
			erro_msg("Macro Trigger Event Overflow! Serious Bug! ");
			printInt16( macroTriggerEventBufferSize );
			print( NL );
			macroTriggerEventBufferSize = 0;
		}
	}

	// If the pause flag is set, only process if the step counter is non-zero
	if ( macroPauseMode )
	{
		if ( macroStepCounter == 0 )
			return;

		// Proceed, decrementing the step counter
		macroStepCounter--;
		dbug_print("Macro Step");
	}

	// Process Trigger Macros
	Trigger_process();


	// Store events processed
	var_uint_t macroTriggerEventBufferSize_processed = macroTriggerEventBufferSize;

	// Reset TriggerList buffer
	macroTriggerEventBufferSize = 0;


	// Process result macros
	Result_process();

	// Signal buffer that we've used it
	Scan_finishedWithMacro( macroTriggerEventBufferSize_processed );

#if defined(_host_)
	// Signal host to read layer state
	Output_callback( "layerState", "" );
#endif

	// Latency measurement
	Latency_end_time( macroLatencyResource );

	// If Macro debug mode is set, clear the USB Buffer
#if defined(Output_USBEnabled_define)
	if ( macroDebugMode == 1 || macroDebugMode == 3 )
	{
		USBKeys_primary.changed = 0;
	}
#endif
}
Exemple #7
0
uint8_t Macro_pressReleaseAdd( void *trigger_ptr )
{
	TriggerEvent *trigger = (TriggerEvent*)trigger_ptr;

	// Error checking
	uint8_t error = 0;
	switch ( trigger->type )
	{
	case TriggerType_Switch1:
	case TriggerType_Switch2:
	case TriggerType_Switch3:
	case TriggerType_Switch4:
	case TriggerType_LED1:
		switch ( trigger->state )
		{
		case ScheduleType_P:
		case ScheduleType_H:
		case ScheduleType_R:
		case ScheduleType_O:
			break;
		default:
			erro_msg("Invalid key state - ");
			error = 1;
			break;
		}
		break;

	case TriggerType_Analog1:
	case TriggerType_Analog2:
	case TriggerType_Analog3:
	case TriggerType_Analog4:
		break;

	// Invalid TriggerGuide type for Interconnect
	default:
		erro_msg("Invalid type - ");
		error = 1;
		break;
	}

	// Check if ScanCode is out of range
	if ( trigger->index > MaxScanCode_KLL )
	{
		warn_msg("ScanCode is out of range/not defined - ");
		error = 1;
	}

	// Display TriggerGuide
	if ( error )
	{
		printHex( trigger->type );
		print(" ");
		printHex( trigger->state );
		print(" ");
		printHex( trigger->index );
		print( NL );
		return 2;
	}

	// Add trigger to the Interconnect Cache
	// During each processing loop, a scancode may be re-added depending on it's state
	for ( var_uint_t c = 0; c < macroInterconnectCacheSize; c++ )
	{
		// Check if the same ScanCode
		if ( macroInterconnectCache[ c ].index == trigger->index )
		{
			// Update the state
			macroInterconnectCache[ c ].state = trigger->state;
			return 0;
		}
	}

	// If not in the list, add it
	macroInterconnectCache[ macroInterconnectCacheSize++ ] = *trigger;

	return 1;
}
Exemple #8
0
// Single strobe matrix scan
// Only goes through a single strobe
// This module keeps track of the next strobe to scan
uint8_t Matrix_single_scan()
{
	// Start latency measurement
	Latency_start_time( matrixLatencyResource );


	// Read systick for event scheduling
	uint32_t currentTime = systick_millis_count;

	// Current strobe
	uint8_t strobe = matrixCurrentStrobe;

	// XXX (HaaTa)
	// Before strobing drain each sense line
	// This helps with faulty pull-up resistors (particularily with SAM4S)
	for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ )
	{
		GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveSetup, Matrix_type );
#if ScanCodeMatrixInvert_define == 2 // GPIO_Config_Pulldown
		GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveLow, Matrix_type );
#elif ScanCodeMatrixInvert_define == 1 // GPIO_Config_Pullup
		GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveHigh, Matrix_type );
#endif
		GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_ReadSetup, Matrix_type );
	}

	// Strobe Pin
	GPIO_Ctrl( Matrix_cols[ strobe ], GPIO_Type_DriveHigh, Matrix_type );

	// Used to allow the strobe signal to propagate, generally not required
	if ( strobeDelayTime > 0 )
	{
		delay_us( strobeDelayTime );
	}

	// Scan each of the sense pins
	for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ )
	{
		// Key position
		uint16_t key = Matrix_colsNum * sense + strobe;
#if ScanCodeRemapping_define == 1
		uint16_t key_disp = matrixScanCodeRemappingMatrix[key];
#else
		uint16_t key_disp = key + 1; // 1-indexed for reporting purposes
#endif

		// Check bounds, before attempting to scan
		// 1-indexed as ScanCode 0 is not used
		if ( key_disp > MaxScanCode_KLL || key_disp == 0 )
		{
			continue;
		}
		volatile KeyState *state = &Matrix_scanArray[ key ];

		// Signal Detected
		// Increment count and right shift opposing count
		// This means there is a maximum of scan 13 cycles on a perfect off to on transition
		//  (coming from a steady state 0xFFFF off scans)
		// Somewhat longer with switch bounciness
		// The advantage of this is that the count is ongoing and never needs to be reset
		// State still needs to be kept track of to deal with what to send to the Macro module
		// Compared against the default state value (ScanCodeMatrixInvert_define), usually 0
		if ( GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_Read, Matrix_type ) != ScanCodeMatrixInvert_define )
		{
			// Only update if not going to wrap around
			if ( state->activeCount < DebounceDivThreshold ) state->activeCount += 1;
			state->inactiveCount >>= 1;
		}
		// Signal Not Detected
		else
		{
			// Only update if not going to wrap around
			if ( state->inactiveCount < DebounceDivThreshold ) state->inactiveCount += 1;
			state->activeCount >>= 1;
		}

		// Check for state change
		// But only if:
		// 1) Enough time has passed since last state change
		// 2) Either active or inactive count is over the debounce threshold

		// Update previous state
		state->prevState = state->curState;

		// Determine time since last decision
		uint32_t lastTransition = currentTime - state->prevDecisionTime;

		// Attempt state transition
		switch ( state->prevState )
		{
		case KeyState_Press:
		case KeyState_Hold:
			if ( state->activeCount > state->inactiveCount )
			{
				state->curState = KeyState_Hold;
			}
			else
			{
				// If not enough time has passed since Hold
				// Keep previous state
				if ( lastTransition < debounceExpiryTime )
				{
					state->curState = state->prevState;
					Macro_keyState( key_disp, state->curState );
					continue;
				}

				state->curState = KeyState_Release;
			}
			break;

		case KeyState_Release:
		case KeyState_Off:
			if ( state->activeCount > state->inactiveCount )
			{
				// If not enough time has passed since Hold
				// Keep previous state
				if ( lastTransition < debounceExpiryTime )
				{
					state->curState = state->prevState;
					Macro_keyState( key_disp, state->curState );
					continue;
				}

				state->curState = KeyState_Press;
			}
			else
			{
				state->curState = KeyState_Off;
			}
			break;

		case KeyState_Invalid:
		default:
			erro_msg("Matrix scan bug!! Report me! - ");
			printHex( state->prevState );
			print(" Col: ");
			printHex( strobe );
			print(" Row: ");
			printHex( sense );
			print(" Key: ");
			printHex( key_disp );
			print( NL );
			break;
		}

		// Update decision time
		state->prevDecisionTime = currentTime;

		// Send keystate to macro module
		Macro_keyState( key_disp, state->curState );

		// Check for activity and inactivity
		if ( state->curState != KeyState_Off )
		{
			matrixStateActiveCount++;
		}
		switch ( state->curState )
		{
		case KeyState_Press:
			matrixStatePressCount++;
			break;

		case KeyState_Release:
			matrixStateReleaseCount++;
			break;

		default:
			break;
		}

		// Matrix Debug, only if there is a state change
		if ( matrixDebugMode && state->curState != state->prevState )
		{
			// Basic debug output
			if ( matrixDebugMode == 1 && state->curState == KeyState_Press )
			{
				printInt16( key_disp );
				print(":");
				printHex( key_disp );
				print(" ");
			}
			// State transition debug output
			else if ( matrixDebugMode == 2 )
			{
				printInt16( key_disp );
				Matrix_keyPositionDebug( state->curState );
				print(" ");
			}
			else if ( matrixDebugMode == 3 )
			{
				print("\033[1m");
				printInt16( key_disp );
				print("\033[0m");
				print(":");
				Matrix_keyPositionDebug( Matrix_scanArray[ key ].prevState );
				Matrix_keyPositionDebug( Matrix_scanArray[ key ].curState );
				print(" 0x");
				printHex_op( state->activeCount, 2 );
				print(" 0x");
				printHex_op( state->inactiveCount, 2 );
				print(" ");
				printInt32( lastTransition );
				print( NL );
			}

		}
	}