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); }
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; }
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; } }
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 ); } } }
// 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( ¯oTriggerEventBuffer[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 }
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; }
// 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 ); } } }