Finding available sound cards on Linux programmatically - c

Is there a way to get a list of available sound cards on the system programmatically using asoundlib and C? I want it with the same information as /proc/asound/cards.

You can iterate over the cards using snd_card_next, starting with a value of -1 to get the 0th card.
Here's sample code; compile it with gcc -o countcards countcards.c -lasound:
#include <alsa/asoundlib.h>
#include <stdio.h>
int main()
{
int totalCards = 0; // No cards found yet
int cardNum = -1; // Start with first card
int err;
for (;;) {
// Get next sound card's card number.
if ((err = snd_card_next(&cardNum)) < 0) {
fprintf(stderr, "Can't get the next card number: %s\n",
snd_strerror(err));
break;
}
if (cardNum < 0)
// No more cards
break;
++totalCards; // Another card found, so bump the count
}
printf("ALSA found %i card(s)\n", totalCards);
// ALSA allocates some memory to load its config file when we call
// snd_card_next. Now that we're done getting the info, tell ALSA
// to unload the info and release the memory.
snd_config_update_free_global();
}
This is code reduced from cardnames.c (which also opens each card to read its name).

Related

Control execution flow for better code design

I'm not sure how exactly to address this problem, I hope you guys can help me.
I'm creating a card game in C (a text-only game that runs on the terminal window) called truco. It is a best-of-3 game that goes until one team reaches 12 or more points, so we have three tricks (let's call it round) each worth 2 points and the game continues with up to three rounds played until one team reaches 12 points.
When playing truco one can "ask for truco" to raise the stake of the match (I'm calling the best of three tricks a match), and the other player can accept, refuse or raise the stake again (essentially accept and then ask for truco).
I'm currently trying to implement this functionality, but my code is probably not the best design as I am suffering to add the "refuse" option, when a player refuses the truco, the other should be given as the winner (of that match) immediately.
And here comes my question, suppose the user asks for truco on the first trick, and the CPU refuses (the game is just you against the CPU for now) how do I "skip" all other code related to other tricks and set the user as the winner for that match?
I don't know how to design the code to allow this kind of feature, in normal cases two or three tricks should be played, but if some player asks for truco and the other refuses the game should ignore the remaining tricks and all other functionalities relating to it, going to the end of the match, updating the score and start another match.
Below I created a small reproducible code to clarify things (just note that I removed and altered a lot of code to keep it simple):
#include <stdio.h>
#include <stdbool.h>
// variable to store the result of the trick and also the final result of the match
int current_result = 0;
void ask_truco()
{
printf("asking truco...\ntruco refused\n");
// game should verify current_result and skip to reset_deck
current_result = 1;
}
void play_trick()
{
printf("playing trick\n");
// simulating that match should be interrupted and finished
ask_truco();
// this should be skipped, but not in normal situations
printf("do something...\n");
}
int check_winner()
{
printf("checking winner\n");
// hard-coded CPU wins
return 2;
}
void reset_deck()
{
printf("resetting deck\n");
}
int play_match(void)
{
// asking for truco here, second and third tricks should not be played
play_trick();
while (true)
{
play_trick(); // while loop helps play second and third trick
current_result = check_winner();
// from ask_truco, I should go back here
if (current_result == 1)
{
printf("increasing user score\n");
break;
}
else if (current_result == 2)
{
printf("increasing cpu score\n");
break;
}
}
// resetting deck of cards
reset_deck();
return 0;
}
int main(void)
{
play_match();
}
In the actual project, I have a few files and functions, if I just use ifs and flags I will end up with a mess, is there a better way to do this? I was wondering if the event-driven design would help me...
Okay, after reading the comments some of you provided me, especially #Fe2O3 and after strungling with myself a little bit I implemented the approach presented to me and manage to solve the problem. I would like to take the opportunity to explain what I did.
First of all, let me explain what my code was before, in my question above I committed the error (as some of you pointed) to remove too much of my code, which prevented you to fully understand what my code was doing.
I will start showing you three files of my project, again some of the things were removed or altered, but this time I think it's pretty concise and still understandable.
My types definition
// types.h
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define TOTAL_CARDS_NUMBER 40
#define TOTAL_HAND_CARDS_NUMBER 3
enum suits
{
spades = 1, // (♠)
hearts, // (♥)
diamonds, // (♦)
clubs // (♣)
};
enum rank
{
four = 1,
five,
six,
seven,
queen,
jack,
king,
ace,
two,
three
};
enum trumpcards
{
facedown = 0,
fourclubs = 14,
sevenhearts = 13,
acespades = 12,
sevendiamonds = 11
};
typedef struct card
{
enum suits suit;
enum rank rank;
bool available;
int value;
} card;
typedef struct player
{
card cards[TOTAL_HAND_CARDS_NUMBER];
int *player_tentos;
} player;
typedef struct player_action
{
int choice;
bool ask_truco;
bool hide_card;
} player_action;
enum round_result
{
TIE,
WIN,
LOSE
};
typedef struct trick
{
enum round_result result;
bool is_tied_by_user;
} trick;
/*
prototypes
*/
void play_hand(card *cards, player *user, player *cpu);
void reset_deck(card *cards);
card ask_cpu_for_card(card *cpu_cards);
card ask_user_for_card(card *user_cards);
My main file
// truco.c
#include "./types.h"
int main(void)
{
printf("Truco\n\n");
card cards[TOTAL_CARDS_NUMBER];
// prepare deck, generating the cards
/* set_deck(cards); */
player user, cpu;
int user_tentos = 0;
int cpu_tentos = 0;
user.player_tentos = &user_tentos;
cpu.player_tentos = &cpu_tentos;
while (user_tentos < 12 && cpu_tentos < 12)
{
play_hand(cards, &user, &cpu);
}
/* show_final_victor(user_tentos, cpu_tentos); */
return 0;
}
Match related file
truco is a best-of-three game for each match, and has a lot of matchs played before the game finishes
// match.c
#include "./types.h"
void play_hand(card *cards, player *user_ptr, player *cpu_ptr)
{
int stake = 2;
int *user_tentos = (*user_ptr).player_tentos;
int *cpu_tentos = (*cpu_ptr).player_tentos;
// distributing cards
/* draw_cards(cards, user_ptr, cpu_ptr); */
trick tricks[3];
int trick = 0;
enum round_result current_result = TIE;
while (true)
{
tricks[trick] = play_trick(user_ptr, cpu_ptr);
current_result = check_winner(tricks);
if (current_result == WIN)
{
// user wins
(*user_tentos) += stake;
break;
}
else if (current_result == LOSE)
{
// cpu wins
(*cpu_tentos) += stake;
break;
}
else if (trick == 2)
{
// third trick in case of tie-tie-tie
break;
}
trick++;
}
// cards should be made available again here
reset_deck(cards);
}
trick play_trick(player *user_ptr, player *cpu_ptr)
{
card *user_cards = (*user_ptr).cards;
card *cpu_cards = (*cpu_ptr).cards;
card user_card, cpu_card;
trick trick;
// ask players for card, possibily asking truco
ask_cards_from_players(user_cards, cpu_cards,
&user_card, &cpu_card);
// populate trick structure with result of current round
/* set_trick_result(user_card, cpu_card, &trick); */
// visual only - show user played cards and round result
/* show_played_cards(user_card, cpu_card); */
return trick;
}
void ask_cards_from_players(
card *user_cards, card *cpu_cards,
card *user_card, card *cpu_card)
{
// ask each player for a card in correct order
// I removed this part to keep it concise and simple
// user can possibily ask truco
*user_card = ask_user_for_card(user_cards);
// cpu could possibily ask truco
// but let's focus on the user for now
*cpu_card = ask_cpu_for_card(cpu_cards);
}
card ask_user_for_card(card *user_cards)
{
// show user cards
/* show_player_cards(user_cards); */
player_action action = {
.choice = 0,
.ask_truco = false};
card card;
// get user choice, including they called truco or not
/* get_choice(&action); */
// get card using choice
/* card = get_card_from_hand(action.choice); */
if (action.ask_truco)
{
// ask cpu if it accepts truco
// if so, maybe the cpu wants to call truco (retruco)
// if retruco, we should ask the user, if they accept truco
// again the user may call retruco now, and so on
// otherwise, the player who called truco should be considered the winner
// if there is a winner in this way, we should set `current_result` accordingly
// the tentos should be updated and the game should skip to line `43` on `play_hand` function
// that is, the `reset_deck` function call
// if truco is just accepted, but retruco is not called
// the game should continue
// and stake for this match should be increased
}
return card;
}
card ask_cpu_for_card(card *cpu_cards)
{
// show cpu cards
/* show_player_cards(cpu_cards); */
card card;
// get a random card for cpu
/* card = get_random_card(cpu_cards); */
return card;
}
That's it, here we have most of the code related to the question, still, some extra things here and there that I kept to maintain everything in context.
As you can see above, my is in case truco is refused. Suppose cpu refuses truco, how do I come back from ask_user_for_card to update user_tentos in the while loop inside play_hand function and immediately go to line 43 and reset_deck(), finishing that match?
Of course, I could use a lot of if statements, maybe change the return type of some functions, or even create some new structures*, but I think that you make the code a little messy, remember this is still a reduced and simplified sample.
* To tangent a little, I was wondering if it's considered a bad practice to create structures with the sole purpose to return more than one thing in a function, even though the properties may not be related...
To solve the problem, the idea #Fe2O3 gave me was a key factor, why not use enums to separate each state of the game and use a loop with a switch to change from one stage to another?
To organize things better I decided to create another file called state-manager.c together with its .h couple. This file is responsible for managing the state of the match, it would store and update the state of the game.
// state-manager.h
enum states
{
END_OF_MATCH = -1,
IDLE,
CHECK_USER_TURN,
SET_ASK_PLAYER_CARD,
ASK_USER_CARD,
ASK_CPU_CARD,
SET_TRICK_RESULT,
SHOW_PLAYED_CARDS,
CHECK_WINNER,
UPDATE_WINNER_TENTOS
};
enum calltruco
{
NO_PLAYER_ASKING_TRUCO,
USER_ASKING_TRUCO,
CPU_ASKING_TRUCO
};
typedef struct state
{
enum states current_state;
enum states previous_state;
enum states next_state;
// which player is asking truco
enum calltruco current_asking_player;
// which player has asked truco
enum calltruco previous_asking_player;
} state;
state get_state();
state update_state(enum states new_state);
state reset_state();
state set_asking_player(enum calltruco new_asking_player);
// state-manager.c
#include "./types.h"
#include "./state-manager.h"
/*
THIS FILE MANAGES THE STATES FOR THE MATCH
Its purpose is to control the flow of the program
when playing three tricks of the game (each match worthing 2-base points)
*/
static state match_state = {
.current_state = IDLE,
.previous_state = IDLE,
.next_state = IDLE,
.current_asking_player = NO_PLAYER_ASKING_TRUCO,
.previous_asking_player = NO_PLAYER_ASKING_TRUCO};
state get_state()
{
return match_state;
}
state update_state(enum states new_state)
{
match_state.previous_state = match_state.current_state;
match_state.current_state = new_state;
return match_state;
}
state reset_state()
{
match_state.current_state = IDLE;
match_state.previous_state = IDLE;
match_state.current_asking_player = NO_PLAYER_ASKING_TRUCO;
match_state.previous_asking_player = NO_PLAYER_ASKING_TRUCO;
return match_state;
}
state set_asking_player(enum calltruco new_asking_player)
{
match_state.previous_asking_player = match_state.current_asking_player;
match_state.current_asking_player = new_asking_player;
return match_state;
}
And in my match.c almost everything was changed
// match.c new version
void play_hand(card *cards, player *user_ptr, player *cpu_ptr)
{
int stake = 2;
state match_state = get_state();
trick tricks[3];
int trick = 0;
enum round_result current_result = TIE;
card user_card, cpu_card;
while (match_state.current_state != END_OF_MATCH)
{
switch (match_state.current_state)
{
case IDLE:
printf("IDLE\n");
// checks and populate the next state
match_state = idle(match_state, trick);
update_state(match_state.next_state);
break;
case CHECK_USER_TURN:
printf("CHECK_USER_TURN\n");
is_user_turn = check_user_turn(tricks[trick - 1]);
update_state(SET_ASK_PLAYER_CARD);
break;
case SET_ASK_PLAYER_CARD:
printf("SET_ASK_PLAYER_CARD\n");
update_state((is_user_turn) ? ASK_USER_CARD : ASK_CPU_CARD);
break;
case ASK_USER_CARD:
printf("ASK_USER_CARD\n");
// now I can just return out of the function it truco is refused
match_state = ask_user_card(match_state,
user_cards,
&user_card,
&current_result,
&stake);
// and update the state accordingly
update_state(match_state.next_state);
break;
case ASK_CPU_CARD:
printf("ASK_CPU_CARD\n");
// do more stuff...
break;
case SET_TRICK_RESULT:
printf("SET_TRICK_RESULT\n");
// do more stuff...
break;
case SHOW_PLAYED_CARDS:
printf("SHOW_PLAYED_CARDS\n");
// do more stuff...
break;
case CHECK_WINNER:
printf("CHECK_WINNER\n");
// do more stuff...
break;
case UPDATE_WINNER_TENTOS:
printf("UPDATE_WINNER_TENTOS\n");
// whatever it does, I can go here anytime I want and break out of the loop
break;
default:
printf("default\n");
update_state(END_OF_MATCH);
break;
}
match_state = get_state();
}
reset_state();
// cards should be made available again here
reset_deck(cards);
}
Again, I naturally just showed related stuff, but I think it is still possible to see the changes, now I have a loop with a switch statement to change from each state of the game to another, I control from where I am to where I will go.
My only concern is, this approach although works great is arguably more complex to read understand and maintain, honestly I'm glad I managed to do this; any other suggestion or comment is appreciated.
Thank you!

Cannot move camera using libuvc

I'm trying to control my camera using libuvc.
I tried this code I modified from the example:
#include <libuvc/libuvc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
uvc_context_t *ctx;
uvc_device_t *dev;
uvc_device_handle_t *devh;
uvc_stream_ctrl_t ctrl;
uvc_error_t res;
/* Initialize a UVC service context. Libuvc will set up its own libusb
* context. Replace NULL with a libusb_context pointer to run libuvc
* from an existing libusb context. */
res = uvc_init(&ctx, NULL);
if (res < 0) {
uvc_perror(res, "uvc_init");
return res;
}
puts("UVC initialized");
/* Locates the first attached UVC device, stores in dev */
res = uvc_find_device(
ctx, &dev,
0, 0, NULL); /* filter devices: vendor_id, product_id, "serial_num" */
if (res < 0) {
uvc_perror(res, "uvc_find_device"); /* no devices found */
} else {
puts("Device found");
/* Try to open the device: requires exclusive access */
res = uvc_open(dev, &devh);
if (res < 0) {
uvc_perror(res, "uvc_open"); /* unable to open device */
} else {
puts("Device opened");
uvc_print_diag(devh, stderr);
//uvc_set_pantilt_abs(devh, 100, 100);
int result = uvc_set_pantilt_abs(devh, 5, 50);
printf("%d\n", result);
//sleep(5);
/* Release our handle on the device */
uvc_close(devh);
puts("Device closed");
}
/* Release the device descriptor */
uvc_unref_device(dev);
}
/* Close the UVC context. This closes and cleans up any existing device handles,
* and it closes the libusb context if one was not provided. */
uvc_exit(ctx);
puts("UVC exited");
return 0;
}
I tried both uvc_set_pantilt_abs and uvc_set_pantilt_rel and both are returning 0 so it means the action is successful. Except the camera does not move.
I'm sure the camera uses UVC because uvc_print_diag indicates
VideoControl:
bcdUVC: 0x0110
Am I doing something wrong? If not how can I troubleshoot it?
I found the answer a while ago but forgot to put it here.
I stumbled upon this project which controls a camera using a commandline tool with libuvc.
After playing a bit with it and compared it with my code I got what I did wrong. He was getting the pantilt data from the camera and then using it to send requests. It seems cameras need to receive a number which must be a multiple of the "step" provided by the camera as the movement unit.
Here's the part where he requests the pantilt information:
int32_t pan;
int32_t panStep;
int32_t panMin;
int32_t panMax;
int32_t tilt;
int32_t tiltStep;
int32_t tiltMin;
int32_t tiltMax;
// get current value
errorCode = uvc_get_pantilt_abs(devh, &pan, &tilt, UVC_GET_CUR);
handleError(errorCode, "Failed to read pan/tilt settings - possibly unsupported by this camera?\n");
// get steps
errorCode = uvc_get_pantilt_abs(devh, &panStep, &tiltStep, UVC_GET_RES);
handleError(errorCode, "Failed to read pan/tilt settings - possibly unsupported by this camera?\n");
// get min
errorCode = uvc_get_pantilt_abs(devh, &panMin, &tiltMin, UVC_GET_MIN);
handleError(errorCode, "Failed to read pan/tilt settings - possibly unsupported by this camera?\n");
// get max
errorCode = uvc_get_pantilt_abs(devh, &panMax, &tiltMax, UVC_GET_MAX);
handleError(errorCode, "Failed to read pan/tilt settings - possibly unsupported by this camera?\n");
Here's the full code

Is it possible to dynamically load new functions to a running C program?

Consider the following C program:
#include <stdio.h>
const int OP_0 = 0;
const int OP_1 = 1;
const int OP_2 = 2;
int op_0(int x) {
return x + 2;
}
int op_1(int x) {
return x * 3 + 1;
}
int op_2(int x) {
return 2 * x * x - 10 * x + 5;
}
int compute(int op, int x) {
switch (op) {
case OP_0: return op_0(x);
case OP_1: return op_1(x);
case OP_2: return op_2(x);
}
return 0;
}
int main() {
int opcode;
int number;
printf("Enter the opcode: ");
scanf("%d", &opcode);
printf("Enter the number: ");
scanf("%d", &number);
printf("Result: %d\n", compute(opcode, number));
return 0;
}
It is a very simple program that lets the user select one of 3 operations to perform on an int input. To use this program, we can compile it with, for instance, gcc program.c -o program, and then run it with ./program. That's all obvious. Suppose, though, that we wanted to add another operation:
int op_3(int x) {
return 900 + x;
}
If we wanted to use this new operation, we'd need to recompile the entire program. Adding a new operation to this program has O(n) complexity, and is slow since it requires a complete recompilation.
My question is: is it possible, in C, to let this program add new native operations (without writing an interpreter)? In other words, is it possible to dynamically compile and add op_3 to the C program above, without having to recompile everything?
For illustration purposes, here is an example of what I have in mind:
int compute(int op, int x) {
// the first time it runs, would load `op_N.dll`
// the next time, would use the loaded version
// so, to add a new operation, we just compile
// it and add `op_N.dll` to this directory
Fun op = dynamic_load(op);
return op(x);
}
The only way I can think of is to compile a new dynamic library that is then opened by the program using dlopen()...
Another way, similar but perhaps more primitive, would be to compile the code into an object file and then load it into a mmaped region with execution permissions, jumping then to it using a function pointer.
To do this, compile the new function using gcc -c, clean the binary code from the headers with objcopy -O binary -j .text. Now in the program open() the resulting file and use the mmap() function to map this file in memory, giving as protections PROT_READ | PROT_EXEC. You'd look up the manuals for all this functions.
Note that I am assuming that you are on a unix system. I don't know much about Windows, but I imagine that something similar could be done with VirtualAlloc().
Well, what you are asking is the "Open Principle of SOLID". To do so, you need to have a dynamic dlsym obviously after dlopen. To have a dynamic dlsym you need to be able to read header files or a file with the proper function prototypes. Yes, you need to cast function pointers, but the typecast depends upon the types of your parameter list.
Edit:
Hard coding dlsym means you have to relink your import library to your executable every time you add a function to your shared object.
OR
You have two shared objects. One is the import library, and the other is the library that you want to add functionality. As David Wheeler said, "All problems of computer science could be solved with another level of indirection, except for the problem with too many layers of indirection.".
Complete noob-proof answer. As the other answers suggested, we can use dlopen and dlsym to dynamically load a shared library on C. First of all, let's create the lib. Save the following file as 0.c
int fn(int x) {
return x * 10;
}
Then, run the following command to create the shared lib:
clang -shared 0.c -o 0
Now, we must edit our compute function to load fn from 0.c dynamically and use it. First, we declare an fn : int -> int function pointer:
int (*fn)(int);
Then, we convert the operation to decimal (since we saved the shared lib as 0, no extension):
char file[256];
sprintf(file, "%d", 0);
Then, we load 0 dynamically:
void *handle = dlopen(file, RTLD_LAZY);
Then, we find fn on that lib, and assing to the fn function pointer:
*(void**)(&fn) = dlsym(LIB[op], "fn");
Then, we can just call it!
fn(5) // will return 50
Here is a complete example, that handles errors and stores the function pointers in a jump table (so we don't need to re-load the lib every time, obviously!):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
const int MAX_OPS = 256;
// Jump-table with available functions
int (*OP[MAX_OPS])(int);
// Array with shared libraries
void* LIB[MAX_OPS];
// Loads an operation dynamically
void load_op(int op) {
int (*fn)(int);
// Generates the file name
char file[256];
sprintf(file, "%d", op);
// Opens the dynamic lib
LIB[op] = dlopen(file, RTLD_LAZY);
// Handles error opening the lib
if (!LIB[op]) {
fprintf(stderr, "Couldn't load operation: %s\n", dlerror());
}
// Creates the function pointer
*(void**)(&fn) = dlsym(LIB[op], "fn");
// Handles error finding the function pointer
if (!fn) {
fprintf(stderr, "Couldn't load operation: %s\n", dlerror());
dlclose(LIB[op]);
}
// Adds to jump table
OP[op] = fn;
}
// Clears the dynlib objects
void close_ops() {
for (int op = 0; op < MAX_OPS; ++op) {
dlclose(LIB[op]);
}
}
// Applies the specified operation to an input
// Requires a shared object file with a name equivalent to the decimal
// representation of op to be loaded on the current directory
int compute(int op, int x) {
if (!OP[op]) {
load_op(op);
}
return OP[op](x);
}
int main() {
int opcode;
int number;
printf("Enter the opcode: ");
scanf("%d", &opcode);
printf("Enter the number: ");
scanf("%d", &number);
printf("Result: %d\n", compute(opcode, number));
return 0;
}
All the credit to the people who took their time to answer my question here and on #c on Libera.Chat. Thank you!

Disable pn53x_check_communication: Input / Output Error message

I'm using libnfc 1.7.1 compiled with c to read from a PN532 reader on a Raspberry Pi. The goal is to make a node for Node-RED that injects the UID of the scanned card or pass errors along about library or reader. I modified the example to give me the UID of a card as the only normal output. I can't have anything printed other than an error when the library can't be loaded, an error when the reader can't be connected, or the UID of the card. I changed the log level to 0 in /etc/nfc/libnfc.conf but my program is still printing "pn53x_check_communication: Input / Output Error" (unwanted) as well as "ERROR: Unable to open NFC device." (wanted) I can't find any way to disable the I/O error message. I looked in the library and found this that returns NFC_EIO which is the I/O error I'm getting, but can't find anywhere that it actually prints that. Short of modifying the library I can't find any way to disable this print. If there is nothing that can be done I can program my node to ignore this output but I would rather eliminate it. My code is below:
#include <stdlib.h>
#include <nfc/nfc.h>
static void
print_long(const uint8_t *pbtData, const size_t szBytes)
{
size_t szPos;
for (szPos = 0; szPos < szBytes; szPos++) {
printf("%03lu", pbtData[szPos]);
}
printf("\n");
}
int
main(int argc, const char *argv[])
{
nfc_device *pnd;
nfc_target nt;
// Allocate only a pointer to nfc_context
nfc_context *context;
// Initialize libnfc and set the nfc_context
nfc_init(&context);
if (context == NULL) {
printf("Unable to init libnfc (malloc)\n");
exit(EXIT_FAILURE);
}
// Open, using the first available NFC device which can be in order of selection:
// - default device specified using environment variable or
// - first specified device in libnfc.conf (/etc/nfc) or
// - first specified device in device-configuration directory (/etc/nfc/devices.d) or
// - first auto-detected (if feature is not disabled in libnfc.conf) device
pnd = nfc_open(context, NULL);
//Send error
if (pnd == NULL) {
printf("ERROR: %s\n", "Unable to open NFC device.");
exit(EXIT_FAILURE);
}
// Set opened NFC device to initiator mode
if (nfc_initiator_init(pnd) < 0) {
nfc_perror(pnd, "nfc_initiator_init");
exit(EXIT_FAILURE);
}
while(true){
// Poll for a ISO14443A (MIFARE) tag
const nfc_modulation nmMifare = {
.nmt = NMT_ISO14443A,
.nbr = NBR_106,
};
//Print decimal version of UID and wait until it's removed to scan again
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) > 0) {
print_long(nt.nti.nai.abtUid, nt.nti.nai.szUidLen);
while (0 == nfc_initiator_target_is_present(pnd, NULL)) {}
}
}
}

Pthread sharing variables with pointers in C

I'm working on a C project using Pthread that needs to share some variables. There are several lines of code written yet and I just realized that using shared global variables doesn't work quite well because of the cache system.
I find on stackoverflow that a solution is to pass the adress of the variable (in my case it's more than one) to the thread function, what does it change?
Since my thread functions call other functions who will modify the globals, it's a bit painful to add a parameter to the chain of called functions where one function modify the globals.
So I was wondering, would it work to declare global pointers for each globals and use them to acess the global instead of the real globals?
I think it's a superficial inderiction but why wouldn't it work after all?
My program is an UDP network protocol whre networks look like rings or circled simple linked list. Instances of the program on the network are called entities.
An entity entity can insert on a ring or ask an entity to create another ring (dupplication), so the other entity would be on two ring.
The interface is sort of a shell where commands can leads to sending messages on the ring. Messages circle all over the rings after being stopped when they have ever been seen.
The shell is in the main thread, there is a thread for message treatment, another to manage insertion, and there is also a thread to detect broken rings. The problems is located in the ring tester thread. The thread initialize a global array (volatile short ring_check[NRING]) of size of the maximum ring numbers for an entity, initialize the first element with 0 according to the actual number of rings and the rest with -1, after that it send a test message in each ring and sleeps during a timeout of 30sec. When the timeout has finished, it checks for the values in the array.
The values are changed by the thread for message treatment, when a test message went went back, it detects it by its content and write -1 to the appropriate ring_check element.
The problem is that after a dupplication, the two rings are tested but the checking for the second failed (ring_check[1] == 0) and I really don't know why... The test message is received, immediately after the sending, after the message treatment modifies ring_check[1] to 0 I print it to see if the change is really made and it prints 1. But about 20 to 30sec later, the ring_tester wake up from his sleeping time and it reads 0 in ring_check[1].
short volatile ring_check[NRING+1];
// The function in the ring tester thread
static void test_ring() {
// initialize ring_check array
debug("ring_tester", GREEN "setting ring_check to -1...");
char port_diff[5];
// send test messages in each rings
int fixed_nring = getnring();
for (int i = fixed_nring+1; i < NRING; ++i) {
ring_check[i] = -1;
}
for (int i = 0; i < fixed_nring + 1; i++) {
debug("ring_tester", GREEN "setting ring_check %d to 0...", i);
ring_check[i] = 0;
itoa4(port_diff, ent.mdiff_port[i]);
debug("ring_tester", GREEN "sending test to ring %d...", i);
sendmessage(i, "TEST", "%s %s", ent.mdiff_ip[i], port_diff);
}
debug("test_ring", GREEN "timeout beginning...");
sleep(timeout);
debug("test_ring", GREEN "end of timeout.");
for (int i = 0; i < fixed_nring + 1 && ring_check[i] != -1; i++) {
debug("test_ring", GREEN "ring_check[%d]:%d", i, ring_check[i]);
if (ring_check[i]) {
debug("test_ring", GREEN "ring %d: checked.", i);
continue;
}
else {
debug("test_ring", GREEN "ring %d: checking failed. Ring broken...", i);
continue;
}
}
// The function called by the message treatment thread
static int action_test(char *message, char *content, int lookup_flag) {
debug("action_test", RED "entering function...");
if (content[15] != ' ' || content[20] != 0) {
debug("action_test", RED "content not following the protocol."\
"content: \"%s\"", content);
return 1;
}
if (lookup_flag) {
char mdiff_port[5];
int fixed_nring = getnring();
for (int i = 0; i < fixed_nring + 1 && ring_check[i] != -1; ++i) {
itoa4(mdiff_port, ent.mdiff_port[i]);
// find ring associated with message and actualize the checking
if (strncmp(content, ent.mdiff_ip[i], 15) == 0 &&
strncmp(&content[16], mdiff_port, 4) == 0 &&
ring_check[i] != -1) {
ring_check[i] = 1;
debug("action_test",
RED "correspondance found, ring_check[%d]:%d", i, ring_check[i]);
return 0;
}
}
}
else {
sendpacket_all(message);
}
return 0;
}
You could define a global structure such as thread_inputparam. Put all the global variables' addresses in it and send to all threads, the adress of this structure variable.
int global1;
struct thread_input {
int *g1;
// add other globals'addresses
}thread_inputparam;
thread_inputparam.g1=&global1;

Resources