c calculate all possible subnets - c

I'm trying to calculate all possible subnets with my Network IP and the Mask:
char *net = "192.168.1.0"
char *mask = "255.255.255.0"
in_addr_t _net = inet_addr(net);
in_addr_t _mask = inet_addr(mask);
int possibleHosts = ntohl(~_mask); // = 255
for (int i=0; i<possibleHosts; i++) { //From 0 to 255
in_addr_t subnet = (_mask & _net) | i; // should calculate the subnets from 192.168.1.0 to 192.168.1.255
struct in_addr in;
in.s_addr = subnet;
char *test = inet_ntoa(in);
printf("%s\n", test); //always prints 192.168.1.0???
}
But the output is always "192.168.1.0". Does anyone know why?

Assuming you want to keep your existing code (and thats a big assumption), remember that _net and _mask are both still in network order, so your OR'd in sub address needs to be as well.
const char *net = "192.168.1.0";
const char *mask = "255.255.255.0";
in_addr_t _net = inet_addr(net);
in_addr_t _mask = inet_addr(mask);
int possibleHosts = ntohl(~_mask);
for (int i=0; i<possibleHosts; i++)
{
in_addr_t subnet = (_mask & _net) | htonl(i); // <<== must be network-order
struct in_addr in;
in.s_addr = subnet;
char *test = inet_ntoa(in);
printf("%s\n", test);
}
Output
192.168.1.0
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.6
192.168.1.7
192.168.1.8
192.168.1.9
192.168.1.10
192.168.1.11
192.168.1.12
192.168.1.13
192.168.1.14
192.168.1.15
192.168.1.16
192.168.1.17
192.168.1.18
192.168.1.19
192.168.1.20
192.168.1.21
192.168.1.22
192.168.1.23
192.168.1.24
192.168.1.25
192.168.1.26
192.168.1.27
192.168.1.28
192.168.1.29
192.168.1.30
192.168.1.31
192.168.1.32
192.168.1.33
192.168.1.34
192.168.1.35
192.168.1.36
192.168.1.37
192.168.1.38
192.168.1.39
192.168.1.40
192.168.1.41
192.168.1.42
192.168.1.43
192.168.1.44
192.168.1.45
192.168.1.46
192.168.1.47
192.168.1.48
192.168.1.49
192.168.1.50
192.168.1.51
192.168.1.52
192.168.1.53
192.168.1.54
192.168.1.55
192.168.1.56
192.168.1.57
192.168.1.58
192.168.1.59
192.168.1.60
192.168.1.61
192.168.1.62
192.168.1.63
192.168.1.64
192.168.1.65
192.168.1.66
192.168.1.67
192.168.1.68
192.168.1.69
192.168.1.70
192.168.1.71
192.168.1.72
192.168.1.73
192.168.1.74
192.168.1.75
192.168.1.76
192.168.1.77
192.168.1.78
192.168.1.79
192.168.1.80
192.168.1.81
192.168.1.82
192.168.1.83
192.168.1.84
192.168.1.85
192.168.1.86
192.168.1.87
192.168.1.88
192.168.1.89
192.168.1.90
192.168.1.91
192.168.1.92
192.168.1.93
192.168.1.94
192.168.1.95
192.168.1.96
192.168.1.97
192.168.1.98
192.168.1.99
192.168.1.100
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104
192.168.1.105
192.168.1.106
192.168.1.107
192.168.1.108
192.168.1.109
192.168.1.110
192.168.1.111
192.168.1.112
192.168.1.113
192.168.1.114
192.168.1.115
192.168.1.116
192.168.1.117
192.168.1.118
192.168.1.119
192.168.1.120
192.168.1.121
192.168.1.122
192.168.1.123
192.168.1.124
192.168.1.125
192.168.1.126
192.168.1.127
192.168.1.128
192.168.1.129
192.168.1.130
192.168.1.131
192.168.1.132
192.168.1.133
192.168.1.134
192.168.1.135
192.168.1.136
192.168.1.137
192.168.1.138
192.168.1.139
192.168.1.140
192.168.1.141
192.168.1.142
192.168.1.143
192.168.1.144
192.168.1.145
192.168.1.146
192.168.1.147
192.168.1.148
192.168.1.149
192.168.1.150
192.168.1.151
192.168.1.152
192.168.1.153
192.168.1.154
192.168.1.155
192.168.1.156
192.168.1.157
192.168.1.158
192.168.1.159
192.168.1.160
192.168.1.161
192.168.1.162
192.168.1.163
192.168.1.164
192.168.1.165
192.168.1.166
192.168.1.167
192.168.1.168
192.168.1.169
192.168.1.170
192.168.1.171
192.168.1.172
192.168.1.173
192.168.1.174
192.168.1.175
192.168.1.176
192.168.1.177
192.168.1.178
192.168.1.179
192.168.1.180
192.168.1.181
192.168.1.182
192.168.1.183
192.168.1.184
192.168.1.185
192.168.1.186
192.168.1.187
192.168.1.188
192.168.1.189
192.168.1.190
192.168.1.191
192.168.1.192
192.168.1.193
192.168.1.194
192.168.1.195
192.168.1.196
192.168.1.197
192.168.1.198
192.168.1.199
192.168.1.200
192.168.1.201
192.168.1.202
192.168.1.203
192.168.1.204
192.168.1.205
192.168.1.206
192.168.1.207
192.168.1.208
192.168.1.209
192.168.1.210
192.168.1.211
192.168.1.212
192.168.1.213
192.168.1.214
192.168.1.215
192.168.1.216
192.168.1.217
192.168.1.218
192.168.1.219
192.168.1.220
192.168.1.221
192.168.1.222
192.168.1.223
192.168.1.224
192.168.1.225
192.168.1.226
192.168.1.227
192.168.1.228
192.168.1.229
192.168.1.230
192.168.1.231
192.168.1.232
192.168.1.233
192.168.1.234
192.168.1.235
192.168.1.236
192.168.1.237
192.168.1.238
192.168.1.239
192.168.1.240
192.168.1.241
192.168.1.242
192.168.1.243
192.168.1.244
192.168.1.245
192.168.1.246
192.168.1.247
192.168.1.248
192.168.1.249
192.168.1.250
192.168.1.251
192.168.1.252
192.168.1.253
192.168.1.254

Core Concept
mask32 = 0xFFFFFFFF = (~0 << 0);
mask31 = 0xFFFFFFFE = (~0 << 1);
mask30 = 0xFFFFFFFB = (~0 << 2);
mask01 = 0x00000000 = (~0 << 31);
[Note: ~0 means inverting all bits of 0, i.e. 0xFFFFFFFF. "<<" means left bit shift.]
Formula
uint32_t mask[ 33 ];
for i = 1 to 32:
mask[i] = ~0 << (32 - i);
Additional
// A function to convert mask from number format to string format.
// See http://www.allredroster.com/iptodec.htm for reference
// Example: maskAsString( 0xC0A80100 ) --> "192.168.1.0"
char const * maskAsString( uint32_t mask );
// .. and also the inverse function
uint32_t stringAsMask( char const * maskString );

Related

Reading a byte from slave_device with spi_transfer

I am writing a driver for a device and am trying to send 2 bytes via spi_transfer and receive 1 byte as answer. My code is following:
int m_read(uint8_t txbuf[]) {
int ret = -1;
uint8_t rx = 0x01;
struct spi_transfer read = {
.tx_buf = &txbuf,
.rx_buf = &rx,
.len = 0x03,
.speed_hz = MAX_HZ,
};
uint8_t *byteRead = (uint8_t *)read.rx_buf;
spi_sync_transfer(slave_device, &read, read.len);
printk("Bytes read: %d\n", *byteRead);
return (ret);
}
While I call the function like:
m_read(mRead);
And mRead is defined as:
uint8_t mRead[] = {0x41, 0x0A};
The output then is 1 but should be a 0x08. It basically just prints the value of rx which didn't change.
I dont really understand what spi_transfer.rx_buf is expected to be. In the documentation it is described with "data to be read" and the data type is void. Can somebody give me a hint how to handle this?

errors encountered while interfacing eeprom with microcontroller

I am not an expert c programmers and in the c code I m getting these kinds of errors. I got many and tried to sort them out but can not solve these. The code is as follows:
/*
* EEPROM.c
* interfacing microchip 24aa64f IC with atmel sam4e
*/
#include <asf.h>
#include "EEPROM_I2C.h"
#define DEVICE_ADDRESS 0x50 // 7-bit device identifier 0101000, (refer datasheet)
//#define EEPROM_NAME 24AA6F
#define I2C_FAST_MODE_SPEED 400000//TWI_BUS_CLOCK 400KHz
#define TWI_CLK_DIVIDER 2
#define TWI_CLK_DIV_MIN 7
#define TWI_CLK_CALC_ARGU 4
#define TWI_CLK_DIV_MAX 0xFF
/*************************** Main function ******************************/
int eeprom_main( void )
{
struct micro24 ptMicro24 ;
typedef struct twi_options twi_options_t;
typedef struct Twi_registers Twi;
char TxBuffer[128] ;
char RxBuffer[128] ;
int BufferIndex;
unsigned int PageCount;
unsigned int error = 0 ;
unsigned int i;
ptMicro24.PageSize = 32;
ptMicro24.NumOfPage = 128;
ptMicro24.EepromSize = 128*32;
ptMicro24.SlaveAddress = DEVICE_ADDRESS;
ptMicro24.EepromName = 64;
/***************************** CLOCK SETTINGS TO GET 400KHz **********************
* Set the I2C bus speed in conjunction with the clock frequency.
* param p_twi Pointer to a TWI instance.
* return value PASS\Fail New speed setting is accepted\rejected
**********************************************************************************/
uint32_t twi_set_speed(struct Twi_registers *Twi, uint32_t ul_speed, uint32_t ul_mck)
//uint32_t twi_set_speed(Twi *p_twi, uint32_t ul_speed, uint32_t ul_mck)
{
uint32_t ckdiv = 0; //clock divider is used to increase both TWCK high and low periods (16-18)
uint32_t c_lh_div; //CHDIV (0-7) and CLDIV (8-15)
if (ul_speed > I2C_FAST_MODE_SPEED) { //ul_speed is the desired I2C bus speed
return FAIL;
}
c_lh_div = ul_mck / (ul_speed * TWI_CLK_DIVIDER) - TWI_CLK_CALC_ARGU; //ul_mck main clock of the device
/* cldiv must fit in 8 bits, ckdiv must fit in 3 bits */
while ((c_lh_div > TWI_CLK_DIV_MAX) && (ckdiv < TWI_CLK_DIV_MIN))
{
ckdiv++; // Increase clock divider
c_lh_div /= TWI_CLK_DIVIDER; //Divide cldiv value
}
/* set clock waveform generator register */
Twi->TWI_CWGR =
TWI_CWGR_CLDIV(c_lh_div) | TWI_CWGR_CHDIV(c_lh_div) |
TWI_CWGR_CKDIV(ckdiv);
return PASS;
}
/************************************ Initialize TWI master mode ************************
* Set the control register TWI_CR by MSEN and SVDIS
* param p_opt Options for initializing the TWI module
* return TWI_SUCCESS if initialization is complete
* twi_options... structure contains clock speed, master clock, chip and smbus
*****************************************************************************************/
uint32_t twi_master_start(struct Twi_registers *Twi, struct twi_options_t *twi_options_t)
//uint32_t twi_master_start(Twi *p_twi, const twi_options_t *p_opt)
{
uint32_t status = TWI_SUCCESS; // status success return code is 0
// Enable master mode and disable slave mode in TWI_CR
Twi -> TWI_CR_START = TWI_CR_START;
Twi->TWI_CR_MSEN = TWI_CR_MSEN; // Set Master Enable bit
Twi->TWI_CR_SVDIS = TWI_CR_SVDIS; // Set Slave Disable bit
/* Select the speed */
//new//if (twi_set_speed(Twi->TWI_SR, twi_options_t->speed, twi_options_t->master_clk) == FAIL)
//if (twi_set_speed(Twi, twi_options_t->speed, twi_options_t->master_clk) == FAIL)
//{
//status = TWI_INVALID_ARGUMENT; /* The desired speed setting is rejected */
//}
if (twi_options_t->smbus == 0)
{
Twi->TWI_CR_QUICK == 0;
status = TWI_INVALID_ARGUMENT;
}
else
if (twi_options_t->smbus == 1)
{
Twi->TWI_CR_QUICK == 1;
status = TWI_SUCCESS;
}
return status;
}
/***************************** WriteByte Function ********************************
This function uses a two bytes internal address (IADR) along with
Internal word address of eeprom.
Return Value: None
***********************************************************************************/
void WriteByte (struct micro24 *ptMicro24, char Data2Write,
unsigned int Address)
//Data2Write is the data to be written n the eeprom
//struct <micro24 *ptMicro24> : Structure of Microchip 24AA Two-wire Eeprom
//unsigned int Address>: Address where to write
{
unsigned int WordAddress;
unsigned int SlaveAddress;
unsigned char p0=0;
TWI_CR_START ==1;
if (ptMicro24->EepromName == 64 )
{
if ( Address > 0xFFFF)
{
p0 = 1;
/* Mask the 17th bit to get the 16th LSB */
WordAddress = Address & 0xFFFF ;
SlaveAddress = ptMicro24->SlaveAddress + (p0<<16) ;
}
else {
SlaveAddress = ptMicro24->SlaveAddress ;
WordAddress = Address ;
}
}
TWI_CR_STOP ==1;
//TWI_WriteSingleIadr(TWI_IADR_IADR,SlaveAddress, WordAddress,
// TWI_MMR_IADRSZ_2_BYTE, &Data2Write); // declared as extern
// to write to internal address, utilizing internal address and master mode register
//}
/******************** Increase Speed Function *****************************
* TWI is accessed without calling TWI functions
/***************************************************************************/
int NumOfBytes, Count;
int status;
uint32_t Buffer;
/* Enable Master Mode of the TWI */
TWI_CR_MSEN == 1;
// Twi.TWI_CR_MSEN ==1;
//TWI_CR->TWI_CR_MSEN = TWI_CR_MSEN ;
/* Set the TWI Master Mode Register */
Twi->TWI_MMR = (SlaveAddress & (~TWI_MMR_MREAD) | (TWI_MMR_IADRSZ_2_BYTE));
/* Set the internal address to access the wanted page */
Twi -> TWI_IADR = WordAddress ;
/* Wait until TXRDY is high to transmit the next data */
status = TWI_SR_TXRDY;
while (!(status & TWI_SR_TXRDY))
status = TWI_SR_TXRDY;
/* Send the buffer to the page */
for (Count=0; Count < NumOfBytes ;Count++ )
{
Twi ->TWI_THR_TXDATA = Buffer++;
/* Wait until TXRDY is high to transmit the next data */
status = TWI_SR_TXRDY;
while (!(status & TWI_SR_TXRDY))
status = TWI_SR_TXRDY;
}
/* Wait for the Transmit complete is set */
status = TWI_SR_TXCOMP;
while (!(status & TWI_SR_TXCOMP))
status = TWI_SR_TXCOMP;
// add some wait function according to datasheet before sending the next data
// e.g: 10ms
// e.g: WaitMiliSecond (10);
}
/****************************** ReadByte Function **************************
This function uses a two bytes internal address (IADR) along with
Internal word address of eeprom.
Return Value: None
****************************************************************************/
char ReadByte (struct micro24 *ptMicro24,
unsigned int Address) //int Address to read
{
unsigned int WordAddress;
unsigned int SlaveAddress;
char Data2Read ;
unsigned char p0=0;
TWI_CR_START == 1;
//p_twi -> TWI_CR_START = TWI_CR_START;
if (ptMicro24->EepromName == 64)
{
if ( Address > 0xFFFF) {
p0 = 1;
// Mask the 17th bit to get the 16th LSB
WordAddress = Address & 0xFFFF ;
SlaveAddress = ptMicro24->SlaveAddress + (p0<<16) ;
}
else {
SlaveAddress = ptMicro24->SlaveAddress ;
WordAddress = Address ;
}
}
//TWI_ReadSingleIadr(TWI_IADR_IADR,SlaveAddress,WordAddress,
// TWI_MMR_IADRSZ_2_BYTE,&Data2Read);
// declared as extern
// to write to internal address, utilizing internal address and master mode register
return (Data2Read);
}
}
errors are:
(24,19): error: storage size of 'ptMicro24' isn't known
67,5): error: dereferencing pointer to incomplete type
Twi->TWI_CWGR =
error: expected identifier before '(' token
#define TWI_CR_START (0x1u << 0) /**< \brief (TWI_CR) Send a START Condition */
error: expected identifier before '(' token
#define TWI_CR_MSEN (0x1u << 2) /**< \brief (TWI_CR) TWI Master Mode Enabled */
error: expected identifier before '(' token
#define TWI_CR_SVDIS (0x1u << 5) /**< \brief (TWI_CR) TWI Slave Mode Disabled */
error: dereferencing pointer to incomplete type
if (twi_options_t->smbus == 0)
It seems missing the declaration of struct micro24, this may be the cause of first error: error: storage size of 'ptMicro24' isn't known.
The same for declaration of Twi_registers, that is causing other errors.
Either you forgot to declare these structs or to include an header file declaring them.

Data request is only returning address value (I2C) [duplicate]

This question already has answers here:
Why am I only receiving the first address byte? (I2C Protocol)
(4 answers)
Closed 6 years ago.
I'm trying to read some values being returned by a sensor device. It is all hooked up fine, but I'm struggling to retrieve data from the sensor, properly.
In the datasheet it says that I should receive bytes in the order: prediction, status, resistance, tvoc.
My terminal keeps spitting out the same value, 23130 (0x5a5a)
This leads me to believe that I'm not properly calling my i2c_start(). In the protocol readme it says to read with I2C_start(SLAVE_READ_ADDRESS);' I tried replacing the address with the so-called read starting point being 0xB5, but that returns my error.
/* Name: main.c
* Author: <insert your name here>
* Copyright: <insert your copyright message here>
* License: <insert your license reference here>
*/
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <uart.h>
#include <i2c_master.h>
#define LED PB5
#define I2C_READ 0x5A
char buffer[10];
uint16_t val = 0;
uint16_t pred = 0;
uint8_t status = 0;
uint8_t resistance = 0;
uint8_t tvoc = 0;
void getVal()
{
if(i2c_start(I2C_READ))
{
//uart_puts("Start ");
val = ((uint8_t)i2c_read_ack())<<8;
val |= i2c_read_ack();
pred = ((uint16_t)i2c_read_ack())<<8;
pred |= i2c_read_ack();
// status = ((uint8_t)i2c_read_ack())<<8;
// status |= i2c_read_ack();
// resistance = ((uint8_t)i2c_read_ack())<<8;
// resistance |= i2c_read_ack();
// tvoc = ((uint8_t)i2c_read_ack())<<8;
// tvoc |= i2c_read_nack();
i2c_stop();
} else
{
uart_puts("Error");
i2c_stop();
}
}
int main(void)
{
init_uart(57600);
i2c_init();
DDRB = _BV(5);
for(;;)
{
getVal();
itoa(val, buffer, 10); //convert decimal to string base 10
uart_puts(buffer);
uart_puts(" ");
itoa(pred, buffer, 10); //convert decimal to string base 10
uart_puts(buffer);
uart_puts(" ");
itoa(status, buffer, 10); //convert decimal to string base 10
uart_puts(buffer);
uart_puts(" ");
itoa(resistance, buffer, 10); //convert decimal to string base 10
uart_puts(buffer);
uart_puts(" ");
itoa(tvoc, buffer, 10); //convert decimal to string base 10
uart_puts(buffer);
uart_puts(" ");
PORTB = 0xFF;
_delay_ms(500);
PORTB = 0x00;
_delay_ms(500);
}
return 0; /* never reached */
}
The datasheet is very unclear and contains a fault as far as addressing is concerned. The address for WRITING is 0xB4 and the address for READING is 0xB5.
The datasheet says the address is:
BIT 7 6 5 4 3 2 1 0
DATA 1 0 1 1 0 1 0 R/W
which corresponds to 0xB4 or 0xB5 depending on the R/W bit beeing set or not. The error they make in the text is that (0)1011010 is 0x5A but the R/W bit is the least significant bit, not the most significant bit.
The i2c_start function in the i2cmaster library returns 1 to indicate an error, not zero
uint8_t i2c_start(uint8_t address)
{
// ... snip ...
// check if the device has acknowledged the READ / WRITE mode
uint8_t twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
return 0;
}
So in your getVal function, you should have
void getVal()
{
if(i2c_start(I2C_READ) == 0) // 0 indicates success
{
In addition, I can't see why you're reading two 16-bit values val and pred from the sensor. The datasheet indicates that pred is the first value returned. You should also read the 8-bit status value to check if the data read is valid.

Combine 2 enums with math operators

I have this enums:
enum bus {
MEDIA_BUS_UNKNOWN,
MEDIA_BUS_VIRTUAL = 1 << 1,
MEDIA_BUS_PCI = 1 << 2,
MEDIA_BUS_USB = 1 << 3,
};
and:
enum bus get_bus( char *sys )
{
FILE *fd;
char file[PATH_MAX];
char s[1024];
if(!strcmp(sys, "/sys/devices/virtual"))
return MEDIA_BUS_VIRTUAL;
snprintf(file, PATH_MAX, "%s/modalias", sys);
fd = fopen(file, "r");
if(!fd)
return MEDIA_BUS_UNKNOWN;
if(!fgets(s, sizeof(s), fd)) {
fclose(fd);
return MEDIA_BUS_UNKNOWN;
}
fclose(fd);
if(!strncmp(s, "pci", 3))
return MEDIA_BUS_PCI;
if(!strncmp(s, "usb", 3))
return MEDIA_BUS_USB;
return MEDIA_BUS_UNKNOWN;
}
I want to create a function to return device(s) with pci or usb bus:
const char *get_device(const enum bus desired_bus)
{
enum bus bus;
...................................................
for( i = 0; i < md->md_size; i++, md_ptr++ ) {
bus = get_bus( md_ptr->sys );
if( ( bus & desired_bus ) == desired_bus )
return md_ptr->node;
}
and call this function to return device(s):
get_device(const enum bus desired_bus)
if request is for devices with pci or usb bus type:
get_device(MEDIA_BUS_PCI | MEDIA_BUS_USB);
It is possible to use math operators for enum?
Sure you can use math operators, but I believe you're looking for bitwise operations, right?. In this case, you enum members values need to be power of two, sou you will be able to do test like this: if(desired_bus & MEDIA_BUS_PCI) if a previously desired_bus |= MEDIA_BUS_PCI was done the if will have MEDIA_BUS_PCI value, so if is true meaning the bit is set.
code example:
enum bus {
MEDIA_BUS_UNKNOWN,
MEDIA_BUS_VIRTUAL = 1 << 1,
MEDIA_BUS_PCI = 1 << 2,
MEDIA_BUS_USB = 1 << 3,
};
/* set flags */
desired_bus |= (MEDIA_BUS_PCI | MEDIA_BUS_USB);
and then:
/* test if flag MEDIA_BUS_PCI was requested.. */
if(desired_bus & MEDIA_BUS_PCI)
In case of it is not set, we get a 0 value that match to our MEDIA_BUS_UNKNOWN value that I think that is a nice to mean error.
EDIT A more complete working C example:
enum bus {
MEDIA_BUS_UNKNOWN,
MEDIA_BUS_VIRTUAL = 1 << 1,
MEDIA_BUS_PCI = 1 << 2,
MEDIA_BUS_USB = 1 << 3,
};
enum bus get_bus( const char *sys );
int main(int argc, char *argv[])
{
const char *sym = argv[1];
enum bus b = get_bus(sym);
if(b & MEDIA_BUS_VIRTUAL)
printf("MEDIA_BUS_VIRTUAL requested\n");
if(b & MEDIA_BUS_USB)
printf("MEDIA_BUS_USB requested\n");
return 0;
}
enum bus get_bus( const char *sys )
{
if(!strcmp("pci", sys))
return MEDIA_BUS_VIRTUAL;
if(!strcmp("usb", sys))
return MEDIA_BUS_USB;
if(!strcmp("pci&usb", sys))
return MEDIA_BUS_VIRTUAL | MEDIA_BUS_USB;
return MEDIA_BUS_UNKNOWN;
}
If you invoke the compiled program with:
a.exe usb: will output:
MEDIA_BUS_USB requested
a.exe "pci&usb" will output:
MEDIA_BUS_VIRTUAL requested
MEDIA_BUS_USB requested
NOTE: You might need to use a type like unsigned instead of enum bus (that highest size is int) to hold a set of enum bus values.
Yes, but for your case, you'll want to make sure that each combination of enum-values is unique, and easily decomposed. To do this, you should make each one a distinct power of two:
enum bus {
MEDIA_BUS_UNKNOWN = 1,
MEDIA_BUS_VIRTUAL = 2,
MEDIA_BUS_PCI = 4,
MEDIA_BUS_USB = 8,
};
(You can then test for a match by writing e.g. desired_bus & MEDIA_BUS_PCI.)
It's a matter of personal taste, but I find using enums to hold bitmasks rather misleading.
I would rather do it with #defines, to be able to define mask combinations easily. For instance:
#define MEDIA_BUS_UNKNOWN 0x00
#define MEDIA_BUS_GPU 0x10
#define MEDIA_BUS_CPU 0x20
#define MEDIA_BUS_VIRTUAL (0x1 | MEDIA_BUS_CPU)
#define MEDIA_BUS_PCI (0x2 | MEDIA_BUS_CPU)
#define MEDIA_BUS_USB (0x3 | MEDIA_BUS_CPU)
#define MEDIA_BUS_AGP (0x4 | MEDIA_BUS_GPU)
#define MEDIA_BUS_PCIE (0x5 | MEDIA_BUS_GPU)
#define MEDIA_BUS_PU_MASK 0x30 // to isolate the PU type
#define MEDIA_BUS_TYPE_MASK 0x0F // to isolate the bus type
typedef int bus_type;
(a rather silly example, but I could not find better without straying too far from the OP's question)

Calculate broadcast address from ip and subnet mask

I want to calculate the broadcast address for:
IP: 192.168.3.1
Subnet: 255.255.255.0
= 192.168.3.255
in C.
I know the way (doing fancy bitwise OR's between the inversed IP and subnet), but my problem is I come from the green fields of MacOSX Cocoa programing.
I looked into the source of ipcal, but wasn't able to integrate it into my code base. There must be a simple ten lines of code somewhere on the internet, I just can't find it.
Could someone point me to a short code example of how to do it in C?
Just calculate:
broadcast = ip | ( ~ subnet )
(Broadcast = ip-addr or the inverted subnet-mask)
The broadcast address has a 1 bit where the subnet mask has a 0 bit.
I understand that the OP had at least a vague understanding of the bit-level arithmetic but was lost on converting the strings to numbers and its inverse. here's a working (with minimal testing anyway) example, using froh42's calculation.
jcomeau#aspire:~/rentacoder/jcomeau/freifunk$ cat inet.c; make inet; ./inet 192.168.3.1 255.255.255.0
#include <arpa/inet.h>
#include <stdio.h>
int main(int argc, char **argv) {
char *host_ip = argc > 1 ? argv[1] : "127.0.0.1";
char *netmask = argc > 2 ? argv[2] : "255.255.255.255";
struct in_addr host, mask, broadcast;
char broadcast_address[INET_ADDRSTRLEN];
if (inet_pton(AF_INET, host_ip, &host) == 1 &&
inet_pton(AF_INET, netmask, &mask) == 1)
broadcast.s_addr = host.s_addr | ~mask.s_addr;
else {
fprintf(stderr, "Failed converting strings to numbers\n");
return 1;
}
if (inet_ntop(AF_INET, &broadcast, broadcast_address, INET_ADDRSTRLEN) != NULL)
printf("Broadcast address of %s with netmask %s is %s\n",
host_ip, netmask, broadcast_address);
else {
fprintf(stderr, "Failed converting number to string\n");
return 1;
}
return 0;
}
cc inet.c -o inet
Broadcast address of 192.168.3.1 with netmask 255.255.255.0 is 192.168.3.255
Could it be?
unsigned broadcast(unsigned ip,unsigned subnet){
unsigned int bits = subnet ^ 0xffffffff;
unsigned int bcast = ip | bits;
return bcast;
}
Edit: I considered that both ip and subnet are without "."
Here is how to do it in C#. for example using ip 10.28.40.149 with netmask 255.255.252.0 returns 10.28.43.255 which is the correct broadcast address. thanks to some code from here
private static string GetBroadcastAddress(string ipAddress, string subnetMask) {
//determines a broadcast address from an ip and subnet
var ip = IPAddress.Parse(ipAddress);
var mask = IPAddress.Parse(subnetMask);
byte[] ipAdressBytes = ip.GetAddressBytes();
byte[] subnetMaskBytes = mask.GetAddressBytes();
if (ipAdressBytes.Length != subnetMaskBytes.Length)
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
for (int i = 0; i < broadcastAddress.Length; i++) {
broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));
}
return new IPAddress(broadcastAddress).ToString();
}
ok whom will look for this code in the future. I have spend sometimes today as I needed this, here is the full code and it works :) simply copy and paste it and then import the required dlls.
private IPAddress CalculateBroadCastAddress(IPAddress currentIP, IPAddress ipNetMask)
{
string[] strCurrentIP = currentIP.ToString().Split('.');
string[] strIPNetMask = ipNetMask.ToString().Split('.');
ArrayList arBroadCast = new ArrayList();
for (int i = 0; i < 4; i++)
{
int nrBCOct = int.Parse(strCurrentIP[i]) | (int.Parse(strIPNetMask[i]) ^ 255);
arBroadCast.Add(nrBCOct.ToString());
}
return IPAddress.Parse(arBroadCast[0] + "." + arBroadCast[1] +
"." + arBroadCast[2] + "." + arBroadCast[3]);
}
private IPAddress getIP()
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip;
}
}
return null;
}
private IPAddress getSubnetMask()
{
NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
IPAddress ip = getIP();
foreach (NetworkInterface interf in Interfaces)
{
UnicastIPAddressInformationCollection UnicastIPInfoCol = interf.GetIPProperties().UnicastAddresses;
foreach (UnicastIPAddressInformation UnicatIPInfo in UnicastIPInfoCol)
{
if (UnicatIPInfo.Address.Equals(ip))
return UnicatIPInfo.IPv4Mask;
}
}
return null;
}
Then just call it like :
IPAddress broadcastip = CalculateBroadCastAddress(getIP(), getSubnetMask());
Happy coding :)

Resources