Originally Posted by
johnmerlino
If I am ANDing it, then what exactly is c_cflag? The thing is it takes many different kind of options. How does it know which option is which?
By reading the documentation:
Originally Posted by
man 3 tcsetattr
tcflag_t c_cflag; /* control modes */
...
c_cflag flag constants:
CBAUD
...
As for knowing which option is which, it is positional. c_cflag is of type tcflag_t; the underlying type is implementation defined, but is some sort of unsigned integer (short/int/long). It it probably at least a 16 bit number, maybe 32. Each option only uses some of those bits. For simplicity's sake, lets assume it's a 16 bit short -- you declare options as a global, so it's initialized to all-bits-zero, thus c_cflag is
Code:
0000 0000 0000 0000 // c_cflag
Assume CLOCAL is the least significant bit, and CREAD is the bit next to it.
Code:
0000 0000 0000 0001 // CLOCAL
0000 0000 0000 0010 // CREAD
You bitwise-OR those together
Code:
0000 0000 0000 0011 // CLOCAL | CREAD
Then you bitwise-OR that with c_cflag, and assign the result to c_cflag (the |= part)
Code:
0000 0000 0000 0000 // c_cflag
|= 0000 0000 0000 0011 // (CLOCAL | CREAD)
-------------------
0000 0000 0000 0011 // -> c_cflag
Next, per the documentation, CSIZE can contain one of 4 values, so it must use at least 2 bits (for this example, we'll assume 00, 01, 10, 11 being the four 2-bit values for CSIZE: CS5, CS6, CS7 and CS8 respectively). Let's also assume CSIZE is uses the two bits next to CREAD
Code:
0000 0000 0000 1100 // CSIZE
1111 1111 1111 0011 // ~CSIZE
0000 0000 0000 0000 // CS5 -- 00 in the CSIZE bits
0000 0000 0000 0100 // CS6 -- 01 in the CSIZE bits
0000 0000 0000 1000 // CS7 -- 10 in the CSIZE bits
0000 0000 0000 1100 // CS8 -- 11 in the CSIZE bits
Now, if we & the bitwise inverse of CSIZE, we will clear those two bits that CSIZE uses, from c_cflag
Code:
1111 1111 1111 0011 // ~CSIZE
&= 0000 0000 0000 0011 // c_cflag
-------------------
0000 0000 0000 0011 // -> c_cflag
Now, we bitwise-OR CS8 into c_flag.
Code:
0000 0000 0000 1100 // CS8
|= 0000 0000 0000 0011 // c_cflag
-------------------
0000 0000 0000 1111 // -> c_cflag
That is how the options are combined into a single variable. Note that, if you did c_cflag = CS8 (plain assignment) instead of |=, you would have assigned 0000 0000 0000 1100 to c_cflag, and the two bits you set previously (CLOCAL and CREAD) would have been cleared.
As for how the function determines which options you set, it basically does the exact opposite of what you do to assemble them:
Code:
if (c_cflag & CLOCAL)
// CLOCAL option was set
else
// CLOCAL option was not set
if ((c_cflag & CSIZE) == CS5)
// CSIZE was set to CS5
...
If you are still having trouble with bitwise operations, then I suggest getting a book and some online tutorials, and working through several examples by hand, to help you understand it conceptually.
EDIT:
Note, the actual position of the individual options within c_cflag, and the values used by CS5 and the like, are irrelevant, that is why they're referred to by names instead of explicitly setting specific bits.