The following files all compile cleanly.
Im on ubuntu linux 14.04 using gcc -Wall -Wextra -pedantic -Wconversion -std=c99 -c to compile each file
Notice there were many small changes to the code to obtain the clean compiles.
You can perform a 'diff' 'cmp' or similar function to highlight the changes made to get the clean compiles.
Some of the changes involved:
- corrected the usage statements in the printusage() function
- corrected the list of #include statements
- corrected declaration of
i as unsigned char rather than char
- corrected declaration of certain other variables from
int to either ssize_t or size_t, as needed
- removed the two different typedef's for
speed_t so the code uses the typedef in the thermos.h header file
- changed return type on a function from
uint32_t to int32_t so function could return a proper -1 value when errors occur
- corrected the indenting of the code for consistency/readability
- for function:
BP_WriteToPirate() carried forward the correct second parameter type from int* to unsigned int*
- properly cast parameters to
t_opt.c_... flags to unsigned int rather than the default int, but only for the not defined NJC
- modified the contents of certain error messages to include the
strerror(errno) string
- corrected exit from
serial_read() to always NUL terminate the input buffer
- added #defines for FALSE and TRUE
- when inputting speed from the parameter list, used
atol() rather than atoi() so data type would match the typedef speed_t
- one still existing problem is the actual value pasted to the cfsetispeed(&t_opt, speed); and cfsetospeed(&t_opt, speed);` functions must be from the set defined in thermos.h not the actual baud rate, because the parameter must be one of the valid bitmap'd values not some long int.
Caveat: my system has no modem nor 'bus pirate` so could not perform extensive testing however: with no (or bad) parameters: the following was output:
-------------------------------------------------------
Bus Pirate binary mode SPI SNIFFER utility v0.2 (CC-0)
http://dangerousprototypes.com
-------------------------------------------------------
&buffer = 0x7ffed4128010
ERROR: Invalid argument(s).
Help Menu
-------------------------------------------------------
Usage:
./untitled -d device -e 1 -p 0
Example Usage: ./untitled -d /dev/ttyUSB0 -s 115200 -e 1 -p 0
Where: -d device is port e.g. /dev/ttyUSB0
-s Speed is port Speed default is 115200
-e ClockEdge is 0 or 1 default is 1
-p Polarity is 0 or 1 default is 0
-r RawData is 0 or 1 default is 0
-------------------------------------------------------
with reasonably good parameters, the following was output:
./untitled -d /dev/ttyUSB0 -s 115200 -e 1 -p 0 -r 0
-------------------------------------------------------
Bus Pirate binary mode SPI SNIFFER utility v0.2 (CC-0)
http://dangerousprototypes.com
-------------------------------------------------------
&buffer = 0x7ffd5a4b35f0
A &buffer = 0x7ffd5a4b35f0
Parameters used: Device = /dev/ttyUSB0, Speed = 115200, Clock Edge= 1, Polarity= 0
Opening Bus Pirate on /dev/ttyUSB0 at 115200bps...
Could not open serial port due to: No such file or directory.Error opening serial port
When I modified the code to ignore the failure to open the serial port then this resulted: with the same counting sequence repeated forever.
0 Sync (0x00/0)
0 Sync (0x00/1)
0 Sync (0x00/2)
...
0 Sync (0x00/120)
0 Sync (0x00/121)
0 Sync (0x00/122)
0 Sync (0x00/0)
and there was no shift in the stack pointer so the buffer[] array did not move
main.c
/*
* This file is part of the Bus Pirate project (http://code.google.com/p/the-bus-pirate/).
*
* Written and maintained by the Bus Pirate project and http://dangerousprototypes.com
*
* To the extent possible under law, the project has
* waived all copyright and related or neighboring rights to Bus Pirate. This
* work is published from United States.
*
* For details see: http://creativecommons.org/publicdomain/zero/1.0/.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
// added
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // getopt(), usleep()
#include <string.h> // strdup()
#include <errno.h>
#include <stdint.h>
#include <signal.h>
#define FALSE (0)
#define TRUE (~FALSE)
#ifdef WIN32
#include <conio.h>
#include <windef.h>
#else
//#include <curses.h>
#endif
#include "buspirate.h"
#include "serial.h"
int modem; //set this to TRUE of testing a MODEM
int verbose;
int disable_comport = 0; //1 to say yes, disable comport, any value to enable port default is 0 meaning port is enable.
int dumphandle; // use by dump file when using the -d dumfile.txt parameter
char *dumpfile;
#define SPI 0x01
int print_usage(char * appname)
{
//print usage
printf("\n\n");
// added '-d com1 in two places
printf("-------------------------------------------------------\n");
printf("\n");
printf(" Usage: \n");
printf(" %s -d device -e [0|1] -p [0|1] -d deviceName\n ",appname);
printf("\n");
printf(" Example Usage: %s -d /dev/ttyUSB0 -s 115200 -e 1 -p 0 \n",appname);
printf("\n");
printf(" Where: -d device is port e.g. /dev/ttyUSB0\n");
printf(" -s Speed is port Speed default is 115200 \n");
printf(" -e ClockEdge is 0 or 1 default is 1 \n");
printf(" -p Polarity is 0 or 1 default is 0 \n");
printf(" -r RawData is 0 or 1 default is 0 \n");
printf("\n");
printf("\n");
printf("-------------------------------------------------------\n");
return 0;
}
int main(int argc, char** argv)
{
int opt;
int fd;
int res;
int c;
int new_state;
int state = 0;
//char buffer[256] = { [0 ... 255] = 0x00 };
char buffer[256] = { 0x00 };
//char *buffer = malloc(sizeof(char) * 256);
unsigned char i; // was char i;
char *param_port = NULL;
char *param_polarity = NULL;
char *param_clockedge = NULL;
char *param_rawdata = NULL;
char *param_speed = NULL;
int speed;
printf("-------------------------------------------------------\n");
printf("\n");
printf(" Bus Pirate binary mode SPI SNIFFER utility v0.2 (CC-0)\n");
printf(" http://dangerousprototypes.com\n");
printf("\n");
printf("-------------------------------------------------------\n");
printf("\n\n");
fprintf(stderr, "&buffer = %p\n", buffer);
if (argc <= 1)
{
printf("ERROR: Invalid argument(s).\n\n");
printf("Help Menu\n");
print_usage(argv[0]);
exit(-1);
}
while ((opt = getopt(argc, argv, "ms:p:e:d:r:")) != -1)
{
// printf("%c \n",opt);
switch (opt)
{
case 'd': // device eg. com1 com12 etc
if ( param_port != NULL)
{
printf("Device/PORT error!\n");
exit(-1);
}
param_port = strdup(optarg);
break;
case 'e': // clock edge
if (param_clockedge != NULL)
{
printf("Clock Edge should be 0 or 1\n");
exit(-1);
}
param_clockedge = strdup(optarg);
break;
case 'p':
if (param_polarity != NULL)
{
printf("Polarity must be 0 or 1\n");
exit(-1);
}
param_polarity = strdup(optarg);
break;
case 's':
if (param_speed != NULL)
{
printf("Speed should be set: eg 115200 \n");
exit(-1);
}
param_speed = strdup(optarg);
speed = atoi(param_speed);
break;
case 'r': // raw data
if (param_rawdata != NULL)
{
printf("Raw Data should be 0 or 1\n");
exit(-1);
}
param_rawdata = strdup(optarg);
break;
case 'm': // modem debugging for testing
modem =TRUE; // enable modem mode
break;
default:
printf("Invalid argument %c", opt);
print_usage(argv[0]);
//exit(-1);
break;
}
} // end while
fprintf(stderr, "A &buffer = %p\n", buffer);
if (param_port==NULL)
{
printf("No serial port set\n");
print_usage(argv[0]);
exit(-1);
}
if (param_clockedge==NULL)
{
param_clockedge=strdup("1");
}
if (param_polarity==NULL)
{
param_polarity=strdup("0");
}
if (param_speed==NULL)
{
param_speed = strdup("115200");
speed = 115200;
}
if (param_rawdata==NULL)
{
param_rawdata=strdup("0");
}
printf("Parameters used: Device = %s, Speed = %s, Clock Edge= %s, Polarity= %s\n",param_port,param_speed,param_clockedge,param_polarity);
//
// Open serial port
//
printf(" Opening Bus Pirate on %s at %dbps...\n", param_port, speed);
fd = serial_open(param_port);
if (fd < 0)
{
fprintf(stderr, "Error opening serial port\n"); //serial_write( fd, "\x0E", 1);
//serial_write( fd, &'0x0E', 1);
return -1;
}
//
// Enter binary mode, then enter a protocol mode
//
serial_setup(fd, (speed_t) speed);
//printf(" Starting SPI sniffer...\n");
if (modem == TRUE)
{ // connected to modem for testing response
serial_write( fd, "ATI3\x0D\0",5 );
usleep(1);
res= serial_read(fd, buffer, sizeof(buffer));
printf("\n %s\n",buffer);
serial_write( fd, "ATI4\x0D\0",5 );
usleep(1);
res= serial_read(fd, buffer, sizeof(buffer));
printf("\n %s\n",buffer);
serial_write( fd, "ATI7\x0D\0",5 );
usleep(1);
res= serial_read(fd, buffer, sizeof(buffer));
printf("\n %s\n",buffer);
}
else
{
fprintf(stderr, " Configuring Bus Pirate...\n");
fprintf(stderr, "B &buffer = %p\n\n", buffer);
BP_EnableMode(fd, SPI); //enter BBIO then SPI
//
//Start sniffer
//
//configure according to user settings
//1000wxyz - SPI config, w=HiZ/3.3v, x=CKP idle, y=CKE edge, z=SMP sample
i = 0x80;
if(strncmp(param_clockedge, "1", 1)==0)
{
i |= 0x02;
}
if(strncmp(param_polarity, "1", 1)==0)
{
i |= 0x04;
}
fprintf(stderr, "C &buffer = %p\n", buffer);
BP_WriteToPirate(fd, &i);
fprintf(stderr, "D &buffer = %p\n", buffer);
// start the sniffer
fprintf(stderr, "start the sniffer\n");
// Yes this is goofy but it kept trying to writ 0xffffff82 instead of 0x0E
char t[] = { 0x0E, 0x00 };
serial_write( fd, t, 1);
//
// Done with setup
//
fprintf(stderr, "E &buffer = %p\n", buffer);
}
printf("Happy sniffing! Ctrl-C (^C) to stop.\n");
// 000011XX - Sniff SPI traffic when CS low(10 ^N)/all(01 ^M)
// 0x60 = ` 30khz
// 0x61 = a 125khz
// 0x67 = b 250khz
// 0x67 = c 1.0 Mhz
// 0x67 = d 2.0 Mhz
// 0x67 = e 2.6 Mhz
// 0x67 = f 4.0 Mhz
// 0x67 = g 8.0 Mhz
//
// Loop and print input from the serial port
/*
** ###
** ### @FIXME: Major issue with a SIGSEGV but I can't figure it out!
** ###
** ### If I attempt to use char buffer[256] it moves from one address to
** ### another in the code above (is that normal?). So I'm guessing
** ### something in the BP_WriteToPirate() (above) is wrong as this is where
** ### the change occurs. I've malloc'd a buffer of 256 bytes and the code
** ### seems happier (ie, no SIGSEGV but no solution either).
** ###
*/
fprintf(stderr, "X FD = %d &buffer = %p\n" , fd, buffer);
while(1)
{
usleep(1);
//res = serial_read(fd, ptr, 100);
res = serial_read(fd, buffer, 100);
if(res == -1)
{
// For some reason we get an error
// So close the port and reopen it
fprintf(stderr, "(%d) Read errno: %s\n", fd, strerror(errno));
if(errno == EBADF)
{ // 9
close(fd);
fd = serial_open(param_port);
if (fd < 0)
{
fprintf(stderr, "Error opening serial port\n");
return -1;
}
//
// Enter binary mode, then enter a protocol mode
//
serial_setup(fd, (speed_t) speed);
}
}
else if(res > 0)
{
for(c = 0; c < res; c++)
{
if(strncmp(param_rawdata, "1", 1)==0)
{
printf("%02X ", (uint8_t) buffer[c]);
}
else
{
switch(state)
{
default:
// fall through
case 0: // waiting CS active
if (buffer[c] == 0x5B)
{
printf("[");
new_state = 1;
}
else
{
printf("0 Sync (0x%02x/%d)\n", buffer[c], c);
new_state = 0;
}
break;
case 1: // check for data or CS inactive
if (buffer[c] == 0x5C)
{
new_state = 2;
}
else if (buffer[c] == 0x5D)
{
printf("]\n");
new_state = 0;
}
else
{
printf("1 Sync (0x%02x)\n", buffer[c]);
new_state = 0;
}
break;
case 2: // MPI
printf("0x%02X(", (uint8_t) buffer[c]);
new_state = 3;
break;
case 3: // MPO
printf("0x%02X)", (uint8_t) buffer[c]);
new_state = 1;
break;
} // end switch
state = new_state;
} // end if
} // end for
} // end if
} // ^C to stop
free(param_port);
free(param_speed);
return 0;
}
serial.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "serial.h"
extern int disable_comport;
extern char *dumpfile;
int serial_setup(int fd, speed_t speed)
{
struct termios t_opt;
#ifdef NJC
int s = tcgetattr(cm11, &oldsb);
if (s < 0)
{
perror("ttopen tcgetattr");
exit(1);
}
newsb = oldsb;
#ifndef BUSPIRATE_h_
#define BUSPIRATE_h_
#include <stdint.h>
int32_t BP_WriteToPirate(int fd, unsigned char * val);
void BP_EnableMode(int fd, char bbmode);
#endif
newsb.c_iflag = IGNBRK | IGNPAR;
newsb.c_oflag = 0;
newsb.c_lflag = ISIG;
newsb.c_cflag = (CLOCAL | B4800 | CS8 | CREAD);
for (s = 0; s < NCC; s++)
{
newsb.c_cc[s] = 0;
}
newsb.c_cc[VMIN] = 1;
newsb.c_cc[VTIME] = 0;
tcsetattr(cm11, TCSADRAIN, &newsb);
#else
/* set the serial port parameters */
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &t_opt);
cfsetispeed(&t_opt, speed);
cfsetospeed(&t_opt, speed);
t_opt.c_cflag |= (unsigned)(CLOCAL | CREAD);
t_opt.c_cflag &= (unsigned)~PARENB;
t_opt.c_cflag &= (unsigned)~CSTOPB;
t_opt.c_cflag &= (unsigned)~CSIZE;
t_opt.c_cflag |= (unsigned)CS8;
t_opt.c_lflag &= (unsigned)~(ICANON | ECHO | ECHOE | ISIG);
t_opt.c_iflag &= (unsigned)~(IXON | IXOFF | IXANY);
t_opt.c_oflag &= (unsigned)~OPOST;
t_opt.c_cc[VMIN] = 0;
//t_opt.c_cc[VTIME] = 10;
t_opt.c_cc[VTIME] = 1;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &t_opt);
#endif
return 0;
} // end function: serial_setup
int serial_write(int fd, char *buf, int size)
{
ssize_t ret = 0;
ret = write(fd, buf, (size_t)size);
fprintf(stderr, "W> ");
for(int i = 0; i < size; i++)
{
fprintf(stderr, "0x%02x ", (unsigned char) buf[i]);
}
fprintf(stderr, "size = %d (%ld)\n", size, ret);
return (int)ret;
} // end function; serial_write
int serial_read(int fd, char *buf, int size)
{
ssize_t len = 0;
ssize_t ret = 0;
int timeout = 0;
while ( len < size)
{
//fprintf(stderr, "FD = %d &buffer = %p (%d)\n" , fd, buf, sizeof(buf));
ret = read(fd, buf+len, (size_t)(size-len));
if (ret == -1)
{
buf[len] = '\0';
return -1;
}
if (ret == 0)
{
timeout++;
if (timeout >= 10)
{
break; // Break out and return from this function
}
else
{
continue; // Just continue the loop
}
}
len += ret;
} // end while
//if( len > 255)
//{
// buf[255] = 0x00; // Buffer's length is 256
//}
//else
//{
buf[len] = 0x00;
//}
return (int)len;
} // end function: serial_read
int serial_open(char *port)
{
int fd;
fd = open(port, O_RDWR | O_NOCTTY);
if (fd == -1)
{
fprintf(stderr, "Could not open serial port due to: %s.", strerror( errno ) );
return -1;
}
return fd;
} // end function: serial_open
int serial_close(int fd)
{
close(fd);
return 0;
} // end function: serial_close
buspirate.c
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "serial.h"
#include "buspirate.h"
//static struct BP_t pBP;
//static uint8_t BP_reversebyte(uint8_t c);
//static char bpbuf[4096];
//static int bpbufcnt;
extern int disable_comport;
extern int dumphandle;
extern int verbose;
extern int modem;
// added
#define FALSE (0)
#define TRUE (~FALSE)
// low lever send command, get reply function
int32_t BP_WriteToPirate(int fd, char *val)
{
int res = -1;
char ret = 0;
serial_write(fd, val, 1);
if (disable_comport != 1)
{ //if comport is enable, we need a response from the port
res = serial_read(fd, &ret, 1);
if( ret != 0x01)
{
if (modem==TRUE)
{
printf("Modem responded with %i byte and with a value of 0X%X\n",res,ret);
}
else
{
printf("ERROR\n");
return -1;
}
}
}
return 0;
} // end function: BP_WriteToPirate
/*
** Put the Buspirate into raw binary mode by sending 20 nulls
** expect BBIO1
** Then put it into SPI raw mode by sending it 0x01
** expect SPI1
*/
void BP_EnableMode(int fd, char bbmode)
{
int ret;
char tmp[100] = { 0x00 };
int done = 0;
//int cmd_sent = 0;
int tries = 0;
printf(" Entering binary mode...\n");
if (fd == (-1))
{ //added because the fd has already returned null
printf("Port does not exist!");
return;
}
// -[ BBIO1 - Binary mode ]-------------------------------------------------
while (!done)
{
tmp[0] = 0x00;
serial_write(fd, tmp, 1);
tries++;
usleep(1);
ret = serial_read(fd, tmp, 5);
if (modem==TRUE)
{
// ???
printf("\nModem Responded = %i\n", ret);
done=1;
}
else
{
if (ret != 5 && tries > 20)
{
fprintf(stderr, "Buspirate did not respond correctly :( %i \n", ret );
exit(-1);
}
else if (strncmp(tmp, "BBIO1", 5) == 0)
{
printf("read returned %i:%s\n", ret, tmp);
done=1;
}
}
if (tries > 25)
{
printf("Buspirate:Too many tries in serial read! -exiting \n - chip not detected, or not readable/writable\n");
exit(-1);
}
} // end while
// -----------------------------------------------------------------------
printf("BP found\n");
// -[ SPI mode ]------------------------------------------------------------
// 00000001 - Enter raw SPI mode, display version string
//
// Once in raw bitbang mode, send 0x01 to enter raw SPI mode. The
// Bus Pirate responds 'SPIx', where x is the raw SPI protocol
// version (currently 1). Get the version string at any time by
// sending 0x01 again.
done = 0;
tmp[0] = bbmode;
tmp[1] = 0x01;
//printf("Sending 0X%02X to port\n",tmp[0]);
serial_write(fd, tmp, 1);
//tries++;
usleep(1);
ret = serial_read(fd, tmp, 5);
if (modem == TRUE)
{
printf("Modem Responded = %i with value %#X\n",ret,tmp[0]);
}
else
{
if ( (ret >= 4) && (strncmp(tmp, "SPI1", 4) == 0))
{
printf("In SPI mode (%d/%s)\n", ret, tmp);
}
else
{
fprintf(stderr, "Buspirate did not respond correctly :( %i [ ", ret );
// reusing tries instead of creating a new var, yeah, just lazy ;-)
for(tries = 0; tries < ret; tries++)
{
fprintf(stderr, "0x%02x ", tmp[tries]);
}
fprintf(stderr, "] %s\n", tmp);
printf("Sending 0X%02X to port\n", 0x01);
tmp[0] = 0x01;
tmp[1] = 0x01;
serial_write(fd, tmp, 1);
usleep(1);
if ( (ret==4) && (strncmp(tmp, "SPI1", 4) == 0))
{
fprintf(stderr, "Yea: %s [ ", tmp ); //
}
else
{
ret = serial_read(fd, tmp, 5);
printf("Sending 0X%02X to port\n", 0x01);
tmp[0] = 0x01;
tmp[1] = 0x01;
serial_write(fd, tmp, 2);
usleep(1);
ret = serial_read(fd, tmp, 5);
if ( (ret==4) && (strncmp(tmp, "SPI1", 4) == 0))
{
fprintf(stderr, "Yea: %s [ ", tmp ); //
}
else
{
if((ret==5) && (strncmp(tmp, "SPI1", 5) == 0))
{
fprintf(stderr, "Yea: %s [ ", tmp ); //
}
else
{
fprintf(stderr, "Buspirate did not respond correctly :( %i [ ", ret );
// reusing tries instead of creating a new var, yeah, just lazy ;-)
for(tries = 0; tries < ret; tries++)
{
fprintf(stderr, "0x%02x ", tmp[tries]);
}
fprintf(stderr, "] %s\n", tmp);
exit(-1);
}
}
} // End if SPI1 else
}
}
} // end function: BP_EnableMode
serial.h
#ifndef MYSERIAL_H_
#define MYSERIAL_H_
/*
#ifdef WIN32
#include <windows.h>
#include <time.h>
#define O_NOCTTY 0
#define O_NDELAY 0
#define B115200 115200
#define B921600 921600
#define OS WINDOWS
int write(int fd, const void* buf, int len);
int read(int fd, void* buf, int len);
int close(int fd);
int open(const char* path, unsigned long flags);
int __stdcall select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfs, const struct timeval* timeout);
#else
#include <unistd.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
#ifdef MACOSX
#include <IOKit/serial/ioss.h>
#include <sys/ioctl.h>
#define B1500000 1500000
#define B1000000 1000000
#define B921600 921600
#endif
#endif
*/
#include <stdint.h>
#ifdef WIN32
#include <windows.h>
#include <time.h>
#define B115200 115200
#define B921600 921600
typedef long speed_t;
#else
#include <unistd.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
#endif
int serial_setup(int fd, speed_t speed);
int serial_write(int fd, char *buf, int size);
int serial_read(int fd, char *buf, int size);
int serial_open(char *port);
int serial_close(int fd);
#endif
buspirate.h
#ifndef BUSPIRATE_h_
#define BUSPIRATE_h_
#include <stdint.h>
int32_t BP_WriteToPirate(int fd, unsigned char * val);
void BP_EnableMode(int fd, char bbmode);
#endif
char buffer[256] = { [0 ... 255] = 0x00 };is a range initializer, and is not yet part of the C standard. It is an extension on some compilers, but makes your code non-portable. - ryykerchar buffer[256] = { [0 ... 255] = 0x00 };is an extension,char buffer[256] = { 0 };does exactly the same thing. - chqrliemain()and a variant of yourBP_WriteToPirate()function) sample, we can't readily predict what you're doing wrong. - Jonathan Leffler