Skip to content

Side ch ctl.c

Function take_reg_idx_string_for_write(char *para)

take_reg_idx_string_for_write: The function of take_reg_idx_string_for_write is to extract a substring from the input string until it encounters specific characters or the end of the string.

parameters: The parameters of this Function. · parameter1: char *para - A pointer to a character array (string) from which the substring will be extracted.

Code Description: The take_reg_idx_string_for_write function processes the input string pointed to by the parameter 'para'. It initializes an index variable 'i' to zero, which is used to traverse the input string. The function enters a loop that continues until it finds one of the specified characters ('d', 'h') or reaches the null terminator (0) of the string. During each iteration of the loop, the current character from 'para' is copied to a global or static character array 'tmp_str' at the index 'i', and 'i' is incremented.

After the loop, the function checks if 'i' is zero, which indicates that no characters were copied. If this is the case, the function returns -1, signaling that no valid characters were found. Next, it checks if the last character processed was the null terminator. If the last character is indeed the null terminator, the function returns -2, indicating that the expected characters ('d' or 'h') were not found before the end of the string. If the loop completes successfully, the function appends a null terminator to 'tmp_str' at the position 'i' and returns the length of the substring copied.

Note: It is important to ensure that the input string 'para' is properly null-terminated and that 'tmp_str' has sufficient space allocated to hold the extracted substring. The function does not handle cases where the input string contains uppercase 'D' or 'H', as these characters are not included in the extraction criteria.

Output Example: If the input string is "exampled", the function will return 7, and 'tmp_str' will contain "example". If the input string is "example", the function will return -2, indicating that neither 'd' nor 'h' was found. If the input string is "d", the function will return -1, indicating that no valid characters were found before the expected character.

graph TD
    A[Start function take_reg_idx_string_for_write] --> B[Initialize index i to 0]
    B --> C[Check if para[i] is not d, D, h, H, or 0]
    C -->|True| D[Assign para[i] to tmp_str[i]]
    D --> E[Increment index i]
    E --> C
    C -->|False| F[Check if i equals 0]
    F -->|True| G[Return -1]
    F -->|False| H[Check if para[i-1] equals 0]
    H -->|True| I[Return -2]
    H -->|False| J[Set tmp_str[i] to 0]
    J --> K[Return index i]
    G --> L[End function]
    I --> L
    K --> L

Function take_reg_val_string_for_write(char *para)

take_reg_val_string_for_write: The function of take_reg_val_string_for_write is to copy a string from the input parameter to a temporary storage and return the length of the copied string.

parameters: The parameters of this Function. · parameter1: char *para - A pointer to a character array (string) that will be copied to the temporary storage.

Code Description: The function take_reg_val_string_for_write takes a single parameter, which is a pointer to a character array (string). It initializes an integer variable i to zero, which will be used as an index to traverse the input string. The function enters a while loop that continues until it encounters the null terminator (0) of the input string. Inside the loop, it copies each character from the input string para to a temporary string tmp_str at the corresponding index i, and increments i after each copy.

After the loop, the function checks if i is equal to zero, which indicates that the input string was empty. If this condition is true, the function returns -1, signaling an error due to the absence of characters to copy. If the input string is not empty, the function appends a null terminator to the end of the tmp_str to properly terminate the copied string. Finally, the function returns the length of the copied string, which is the value of i.

Note: It is important to ensure that the tmp_str has sufficient allocated memory to hold the contents of the input string, including the null terminator. Additionally, the function does not perform any bounds checking on the input string, so care should be taken to avoid buffer overflows.

Output Example: If the input string is "Hello", the function will return 5, indicating that 5 characters were copied to tmp_str. If the input string is empty, the function will return -1.

graph TD
    A[Start function take_reg_val_string_for_write] --> B[Initialize index i to 0]
    B --> C[Check if para[i] is not equal to 0]
    C -->|Yes| D[Assign para[i] to tmp_str[i]]
    D --> E[Increment index i]
    E --> C
    C -->|No| F[Check if i is equal to 0]
    F -->|Yes| G[Return -1]
    F -->|No| H[Set tmp_str[i] to 0]
    H --> I[Return i]
    G --> J[End function]
    I --> J
    J[End function]

Function all_zero_in_string(char *para)

all_zero_in_string: The function of all_zero_in_string is to determine if a given string consists entirely of the character '0'.

parameters: The parameters of this Function. · parameter1: char *para - A pointer to a character array (string) that is to be checked for all zero characters.

Code Description: The all_zero_in_string function takes a single string parameter and checks whether the entire string is made up of the character '0'.

The function begins by declaring an integer variable i for indexing and another integer variable check_len which stores the length of the input string para using the strlen function. If the length of the string is zero (i.e., the string is empty), the function returns -1, indicating an invalid input.

Next, the function initializes i to 0 and enters a while loop that increments i as long as the character at the current index of para is '0'. This loop effectively counts how many leading '0' characters are present in the string.

After exiting the loop, the function checks if i is equal to check_len. If they are equal, it means that every character in the string was '0', and the function returns 1, indicating that the string consists entirely of '0's. If i is not equal to check_len, the function returns 0, indicating that the string contains characters other than '0'.

Note: It is important to ensure that the input string is not NULL before calling this function to avoid undefined behavior. The function also returns -1 for an empty string, which should be handled appropriately by the caller.

Output Example: - If the input string is "0000", the function will return 1. - If the input string is "0001", the function will return 0. - If the input string is "", the function will return -1.

graph TD
    A[Start] --> B[Calculate length of para]
    B --> C{Is length zero?}
    C -- Yes --> D[Return -1]
    C -- No --> E[Initialize i to 0]
    E --> F{Is para[i] equal to '0'?}
    F -- Yes --> G[Increment i]
    F -- No --> H{Is i equal to check_len?}
    H -- Yes --> I[Return 1]
    H -- No --> J[Return 0]
    G --> F
    D --> Z[End]
    I --> Z
    J --> Z

Function atoi_my(char *para)

atoi_my: The function of atoi_my is to convert a string representation of a number into a long integer, while handling specific edge cases.

parameters: The parameters of this Function. · parameter1: char *para - A pointer to a string that represents the number to be converted.

Code Description: The atoi_my function begins by calling the helper function all_zero_in_string, passing the input string 'para' to it. This function checks if the string contains only zeros and returns a long integer value based on the result. The return value is stored in the variable 'ret'.

If 'ret' is less than 0, indicating an error condition, the function immediately returns -1. If 'ret' equals 1, which signifies that the string consists entirely of zeros, the function returns 0.

If the string contains valid numeric characters, the function proceeds to convert the string to a long integer using the standard library function atol. The result of this conversion is stored back in 'ret'.

After the conversion, if 'ret' equals 0, the function again returns -1, indicating that the conversion did not yield a valid number (this could happen if the input string was "0" or if the string was invalid). If 'ret' contains a valid long integer, it is returned as the output of the function.

Note: Users should ensure that the input string is properly formatted as a number. The function does not handle non-numeric characters or strings that exceed the range of a long integer. Additionally, the behavior of the function when provided with NULL or invalid pointers is not defined.

Output Example: - If the input string is "12345", the function will return 12345. - If the input string is "0000", the function will return 0. - If the input string is "abc", the function will return -1. - If the input string is NULL, the function's behavior is undefined.

graph TD
    A[Start] --> B[Call all_zero_in_string with para]
    B --> C[Store result in ret]
    C --> D{Is ret less than 0?}
    D -- Yes --> E[Return -1]
    D -- No --> F{Is ret equal to 1?}
    F -- Yes --> G[Return 0]
    F -- No --> H[Call atol with para]
    H --> I[Store result in ret]
    I --> J{Is ret equal to 0?}
    J -- Yes --> K[Return -1]
    J -- No --> L[Return ret]
    E --> M[End]
    G --> M
    L --> M

Function hextoi_my(char *para)

hextoi_my: The function of hextoi_my is to convert a hexadecimal string to a long integer.

parameters: The parameters of this Function. · parameter1: char *para - A pointer to a string that represents a hexadecimal number.

Code Description: The hextoi_my function begins by calling another function, all_zero_in_string, passing the input string para as an argument. This function checks if the string contains only zeros and returns a long integer value. The return value is stored in the variable ret.

If ret is less than 0, the function returns -1, indicating an error condition. If ret equals 1, it indicates that the string consists entirely of zeros, and the function returns 0, which is the expected result for a zero value in hexadecimal.

If the string contains valid hexadecimal characters, the function proceeds to convert the string to an unsigned long integer using the strtoul function, specifying a base of 16 for hexadecimal conversion. The result of this conversion is again stored in ret.

If the conversion results in a value of 0, the function returns -1, indicating an error, as a valid hexadecimal string should not convert to zero unless it is the string "0". If the conversion is successful and ret holds a valid long integer, the function returns this value.

Note: It is important to ensure that the input string is properly formatted as a hexadecimal number. The function does not handle invalid characters or strings that are too large to be represented as a long integer. Users should also be aware that the function returns -1 for both error conditions and for the case of an invalid conversion resulting in zero.

Output Example: - If the input string is "1A3F", the function would return 6719. - If the input string is "0000", the function would return 0. - If the input string is "GHIJ", the function would return -1, indicating an error due to invalid hexadecimal characters.

graph TD
    A[Start] --> B[Call all_zero_in_string with para]
    B --> C{Check result}
    C -->|ret < 0| D[Return -1]
    C -->|ret == 1| E[Return 0]
    C -->|ret >= 2| F[Call strtoul with para and base 16]
    F --> G{Check strtoul result}
    G -->|ret == 0| H[Return -1]
    G -->|ret > 0| I[Return ret]
    D --> J[End]
    E --> J
    H --> J
    I --> J

Function parse_para_string(char para, int action_flag, int reg_type, int reg_idx, unsigned int reg_val, int interval_ms)

parse_para_string: The function of parse_para_string is to parse a parameter string for specific actions related to side channel control, including getting information, reading from, and writing to registers.

parameters: The parameters of this Function. · para: A character pointer to the input parameter string that contains the command and associated values. · action_flag: A pointer to an integer that will be set to indicate the action type (get, read, or write). · reg_type: A pointer to an integer that will be set to indicate the type of register (hardware or software). · reg_idx: A pointer to an integer that will be set to the index of the register being accessed. · reg_val: A pointer to an unsigned integer that will be set to the value for a register write operation. · interval_ms: A pointer to an integer that will be set to the interval in milliseconds for getting side information.

Code Description: The parse_para_string function begins by determining the length of the input parameter string. It checks for validity, ensuring the string is neither empty nor exceeds a predefined maximum length. If the string starts with 'g', it indicates a request to get side information. If no additional input is provided, a default interval of 100 milliseconds is set. If an interval is specified, it is converted from a string to an integer, with validation to ensure it is non-negative.

If the string starts with 'r', it signifies a read command. The function checks the next character to determine the register type (hardware or software) and then extracts the register index, ensuring it falls within the valid range of 0 to 31.

For a write command indicated by a string starting with 'w', the function requires a longer input. It again checks the register type and extracts the register index. It also determines whether the subsequent value is in decimal or hexadecimal format, validating the input accordingly. The function converts the value to the appropriate format and checks for validity.

If any of the checks fail, the function returns specific error codes to indicate the type of error encountered, allowing for easier debugging and handling of invalid inputs.

Note: It is essential to ensure that the input string adheres to the expected format for the function to operate correctly. Invalid inputs will result in error messages and specific return codes, which should be handled appropriately by the calling function.

Output Example: - If the input string is "g", the function will return 0, and interval_ms will be set to 100. - If the input string is "rhw2", the function will return 0, action_flag will be set to ACTION_REG_READ, reg_type will be set to REG_TYPE_HARDWARE, and reg_idx will be set to 2. - If the input string is "wsh3d255", the function will return 0, action_flag will be set to ACTION_REG_WRITE, reg_type will be set to REG_TYPE_SOFTWARE, reg_idx will be set to 3, and reg_val will be set to 255.

graph TD
    A[Start] --> B[Calculate length of parameter string]
    B --> C{Is length 0 or greater than MAX_PARA_STRING_LEN?}
    C -- Yes --> D[Print error message for length]
    D --> E[Return -1]
    C -- No --> F{Is first character 'g'?}
    F -- Yes --> G[Set action_flag to ACTION_SIDE_INFO_GET]
    G --> H{Is length 1?}
    H -- Yes --> I[Set interval_ms to 100]
    I --> J[Print default interval message]
    J --> K[Return 0]
    H -- No --> L[Convert para+1 to interval_ms]
    L --> M{Is interval_ms < 0?}
    M -- Yes --> N[Set interval_ms to 100]
    N --> O[Print invalid interval message]
    O --> K
    M -- No --> K
    F -- No --> P{Is length 2?}
    P -- Yes --> Q[Print lack of input message]
    Q --> E
    P -- No --> R{Is first character 'r'?}
    R -- Yes --> S[Set action_flag to ACTION_REG_READ]
    S --> T{Is second character 'h'?}
    T -- Yes --> U[Set reg_type to REG_TYPE_HARDWARE]
    T -- No --> V{Is second character 's'?}
    V -- Yes --> W[Set reg_type to REG_TYPE_SOFTWARE]
    V -- No --> X[Set reg_type to REG_TYPE_INVALID]
    X --> Y[Print invalid register type message]
    Y --> E
    U --> Z[Convert para+2 to reg_idx]
    W --> Z
    Z --> AA{Is reg_idx < 0 or > 31?}
    AA -- Yes --> AB[Print invalid register index message]
    AB --> E
    AA -- No --> E
    R -- No --> AC{Is first character 'w'?}
    AC -- Yes --> AD[Set action_flag to ACTION_REG_WRITE]
    AD --> AE{Is second character 'h'?}
    AE -- Yes --> AF[Set reg_type to REG_TYPE_HARDWARE]
    AE -- No --> AG{Is second character 's'?}
    AG -- Yes --> AH[Set reg_type to REG_TYPE_SOFTWARE]
    AG -- No --> AI[Set reg_type to REG_TYPE_INVALID]
    AI --> AJ[Print invalid register type message]
    AJ --> E
    AF --> AK[Get register index string for write]
    AH --> AK
    AK --> AL{Is num_char_reg_idx < 0?}
    AL -- Yes --> AM[Print invalid register index input message]
    AM --> E
    AL -- No --> AN[Convert tmp_str to reg_idx]
    AN --> AO{Is reg_idx < 0 or > 31?}
    AO -- Yes --> AP[Print invalid register index message]
    AP --> E
    AO -- No --> AQ{Is character at position 2+num_char_reg_idx 'd'?}
    AQ -- Yes --> AR[Set hex_flag to 0]
    AQ -- No --> AS{Is character at position 2+num_char_reg_idx 'h'?}
    AS -- Yes --> AT[Set hex_flag to 1]
    AS -- No --> AU[Print invalid hex/decimal flag message]
    AU --> E
    AR --> AV[Get register value string for write]
    AT --> AV
    AV --> AW{Is num_char_reg_val < 0?}
    AW -- Yes --> AX[Print invalid register value input message]
    AX --> E
    AW -- No --> AY{Is hex_flag 0?}
    AY -- Yes --> AZ[Convert tmp_str to reg_val]
    AZ --> BA{Is reg_val < 0?}
    BA -- Yes --> BB[Print invalid register value input of decimal number message]
    BB --> E
    BA -- No --> E
    AY -- No --> BC[Convert tmp_str to reg_val using hextoi_my]
    BC --> BD{Is reg_val < 0?}
    BD -- Yes --> BE[Print invalid register value input of hex number message]
    BE --> E
    BD -- No --> E
    E --> Z

Function print_usage(void)

print_usage: The function of print_usage is to display the usage instructions for the side_ch_ctl command-line tool.

parameters: The parameters of this Function. · parameter1: None

Code Description: The print_usage function is designed to provide users with clear and concise instructions on how to use the side_ch_ctl command-line tool. It does not take any parameters and does not return any value. The function utilizes the printf function from the standard input/output library to print a series of formatted strings to the console.

The first line of output specifies the general usage format: "Usage: side_ch_ctl parameter_string". This informs the user that the command requires a parameter string to function correctly.

Subsequent lines provide specific examples of valid commands that can be executed with the tool: - The command "write 987 to hardware register 3" is illustrated with the format "wh3d987", where: - 'w' indicates the write operation, - 'h' specifies that the target is a hardware register, - '3' denotes the register index, - 'd' indicates that the value is in decimal format, - '987' is the actual value to be written.

  • The command "write 0x3db to software register 19" is shown as "ws19h3db", where:
  • 'w' indicates the write operation,
  • 's' specifies that the target is a software register,
  • '19' denotes the register index,
  • 'h' indicates that the value is in hexadecimal format,
  • '3db' is the hexadecimal value to be written.

  • The command "read software register 23" is presented as "rs23", where:

  • 'r' indicates the read operation,
  • 's' specifies that the target is a software register,
  • '23' denotes the register index.

  • Finally, the command "get csi and equalizer output" is illustrated with "g400", where:

  • 'g' indicates the get operation,
  • '400' specifies the interval in milliseconds (every 400ms), and it is noted that no or incorrect input defaults to 100ms.

This function serves as a helpful guide for users to understand the expected input format and the operations they can perform with the side_ch_ctl tool.

Note: It is important for users to refer to the output of this function when they are unsure about the command syntax or need examples of valid commands to ensure proper usage of the tool.

graph TD
    A[Start print_usage function] --> B[Print usage message]
    B --> C[Print example usage for writing to hardware register]
    C --> D[Print example usage for writing to software register]
    D --> E[Print example usage for reading software register]
    E --> F[Print example usage for getting csi and equalizer output]
    F --> G[End print_usage function]

Function sigint_callback_handler(int signum)

sigint_callback_handler: The function of sigint_callback_handler is to handle the SIGINT signal by printing a message and setting a flag to indicate that the program should exit.

parameters: The parameters of this Function. · parameter1: int signum - This parameter represents the signal number that was caught, specifically the SIGINT signal in this context.

Code Description: The sigint_callback_handler function is designed to respond to the SIGINT signal, which is typically generated when a user interrupts a program by pressing Ctrl+C in the terminal. When this signal is received, the function executes the following actions:

  1. It uses the fprintf function to print a message to the standard output (stdout), indicating that a signal has been caught. The message includes the signal number (signum) that was received, allowing the user to see which signal triggered the handler.

  2. The function then sets the global variable do_exit to true. This variable acts as a flag to signal other parts of the program that an exit condition has been triggered, allowing for a graceful shutdown of the application.

This function is crucial for managing the program's behavior in response to user interruptions, ensuring that the application can terminate cleanly and provide feedback to the user.

Note: It is important to ensure that the global variable do_exit is properly handled in other parts of the program to facilitate a controlled exit. Additionally, this function should be registered as a signal handler for SIGINT using the signal() or sigaction() functions in the main program to ensure it is invoked when the signal is received.

graph TD
    A[Receive signal] --> B[Log caught signal]
    B --> C[Set do_exit to true]

Function main(const int argc, char * const argv[])

main: The function of main is to initialize the application, parse command-line arguments, set up communication with the kernel and a remote server, and handle the main processing loop.

parameters: The parameters of this Function. · parameter1: const int argc - The number of command-line arguments passed to the program. · parameter2: char * const argv[] - An array of strings representing the command-line arguments.

Code Description: The main function begins by declaring several local variables used throughout the function, including flags for actions and types, socket descriptors, and buffers for communication. It first checks if the required command-line argument is provided; if not, it prints an error message and usage instructions, then exits.

The function proceeds to parse the command-line argument using the parse_para_string function, which extracts values for action flags, register types, indices, values, and an interval in milliseconds. If the parsing fails, an error message is displayed, and the function exits.

Signal handling is set up to catch interrupts, specifically SIGINT, to ensure graceful termination of the application. A socket is created for communication with the kernel using the Netlink protocol. The source and destination addresses for the socket are initialized, and the socket is bound to the source address.

The function then enters a loop that continues until a termination condition is met. Within this loop, it prepares a Netlink message, populates it with the parsed command values, and sends it to the kernel. After sending the message, it waits for a response from the kernel, processes the received data, and, depending on the action flag, may send the data to a remote server via a UDP socket.

The loop also includes logic to handle the frequency of operations, printing status updates every 64 iterations. The function sleeps for a specified interval between iterations to control the rate of processing.

Finally, upon exiting the loop, the function closes the sockets and returns the result of the operations performed.

Note: It is important to ensure that the command-line arguments are correctly formatted and that the kernel is set up to handle the Netlink messages. Proper error handling is crucial for robust application behavior.

Output Example: A successful execution of the program with valid arguments might produce output similar to:

parse: ret 0
   tx: action_flag 1 reg_type 2 reg_idx 3 reg_val 100 interval_ms 50
   rx: size 16 val 100 0x00000064
loop 64 side info count 1

graph TD
    A[Start main function] --> B[Check argument count]
    B -->|argc < 2| C[Print argument needed message]
    C --> D[Call print_usage]
    D --> E[Return ret]
    B -->|argc >= 2| F[Set value_only_flag]
    F --> G[Call parse_para_string]
    G -->|ret < 0| H[Print wrong input message]
    H --> D
    G -->|ret >= 0| I[Print parsed values]
    I --> J[Set up signal handlers]
    J -->|signal setup failed| K[Print SIG_ERR message]
    K --> E
    J -->|signal setup successful| L[Create socket]
    L -->|sock_fd < 0| M[Print socket_fd error]
    M --> E
    L -->|sock_fd >= 0| N[Initialize source address]
    N --> O[Initialize destination address]
    O --> P[Allocate memory for nlmsghdr]
    P --> Q[Setup UDP socket]
    Q -->|s < 0| R[Print socket error message]
    R --> S[Set socket_ok to 0]
    Q -->|s >= 0| T[Setup server address]
    T --> U[Start main loop]
    U -->|do_exit is false| V[Prepare nlmsghdr]
    V --> W[Send message to kernel]
    W --> X[Receive message from kernel]
    X --> Y[Calculate side_info_size]
    Y -->|action_flag != ACTION_SIDE_INFO_GET| Z[Print received values]
    Z --> AA[Break loop]
    Y -->|action_flag == ACTION_SIDE_INFO_GET| AB[Check socket_ok and side_info_size]
    AB -->|socket_ok and side_info_size valid| AC[Send to remote server]
    AC --> AD[Increment side_info_count]
    AB -->|socket not ok or size invalid| AE[Continue loop]
    U --> AF[Increment loop_count]
    AF -->|loop_count % 64 == 0| AG[Print loop status]
    AG --> AH[Sleep for interval_ms]
    AH --> U
    U --> AI[Close sockets]
    AI --> E[Return ret]
    E --> AJ[End main function]