diff options
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | cli.c | 92 | ||||
| -rw-r--r-- | common.mk | 3 | ||||
| -rw-r--r-- | driver/base.c | 1 | ||||
| -rw-r--r-- | error.h | 1 | ||||
| -rw-r--r-- | ipecamera.h | 86 | ||||
| -rw-r--r-- | ipecamera/image.c | 287 | ||||
| -rw-r--r-- | ipecamera/image.h | 22 | ||||
| -rw-r--r-- | ipecamera/ipecamera.h | 6 | ||||
| -rw-r--r-- | ipecamera/model.c (renamed from ipecamera.c) | 18 | ||||
| -rw-r--r-- | ipecamera/model.h | 110 | ||||
| -rw-r--r-- | pci.c | 287 | ||||
| -rw-r--r-- | pci.h | 8 | ||||
| -rw-r--r-- | pcilib.h | 59 | 
14 files changed, 866 insertions, 117 deletions
| @@ -14,7 +14,7 @@ include common.mk  ###############################################################  # Target definitions -OBJECTS = pci.o ipecamera.o default.o tools.o +OBJECTS = pci.o  default.o tools.o ipecamera/model.o ipecamera/image.o  libpcilib.so: $(OBJECTS)  	echo -e "LD \t$@" @@ -26,6 +26,7 @@ pci: cli.o libpcilib.so  install: pci  	install -m 644 pcilib.h $(DESTDIR)/include +	install -m 644 ipecamera/ipecamera.h $(DESTDIR)/include  	if [ -d $(DESTDIR)/lib64 ]; then install -m 755 libpcilib.so $(DESTDIR)/lib64; else install -m 755 libpcilib.so $(DESTDIR)/lib; fi  	install -m 755 pci $(DESTDIR)/bin  	ldconfig @@ -18,7 +18,6 @@  #include <getopt.h>  #include "pci.h" -#include "ipecamera.h"  #include "tools.h"  #include "kernel.h" @@ -50,7 +49,9 @@ typedef enum {      MODE_READ,      MODE_READ_REGISTER,      MODE_WRITE, -    MODE_WRITE_REGISTER +    MODE_WRITE_REGISTER, +    MODE_RESET, +    MODE_GRAB  } MODE;  typedef enum { @@ -60,11 +61,14 @@ typedef enum {      OPT_ACCESS = 'a',      OPT_ENDIANESS = 'e',      OPT_SIZE = 's', +    OPT_OUTPUT = 'o',      OPT_INFO = 'i',      OPT_BENCHMARK = 'p',      OPT_LIST = 'l',      OPT_READ = 'r',      OPT_WRITE = 'w', +    OPT_GRAB = 'g', +    OPT_RESET = 128,      OPT_HELP = 'h',  } OPTIONS; @@ -75,11 +79,14 @@ static struct option long_options[] = {      {"access",			required_argument, 0, OPT_ACCESS },      {"endianess",		required_argument, 0, OPT_ENDIANESS },      {"size",			required_argument, 0, OPT_SIZE }, +    {"size",			required_argument, 0, OPT_OUTPUT },      {"info",			no_argument, 0, OPT_INFO },      {"list",			no_argument, 0, OPT_LIST }, +    {"reset",			no_argument, 0, OPT_RESET },      {"benchmark",		no_argument, 0, OPT_BENCHMARK },      {"read",			optional_argument, 0, OPT_READ },      {"write",			optional_argument, 0, OPT_WRITE }, +    {"grab",			optional_argument, 0, OPT_GRAB },      {"help",			no_argument, 0, OPT_HELP },      { 0, 0, 0, 0 }  }; @@ -108,6 +115,8 @@ void Usage(int argc, char *argv[], const char *format, ...) {  "	-p		- Performance Evaluation\n"  "	-r <addr|reg>	- Read Data/Register\n"  "	-w <addr|reg>	- Write Data/Register\n" +"	-g <event>	- Grab Event\n" +"	--reset		- Reset board\n"  "	--help		- Help message\n"  "\n"  "  Addressing:\n" @@ -121,6 +130,7 @@ void Usage(int argc, char *argv[], const char *format, ...) {  "	-s <size>	- Number of words (default: 1)\n"  "	-a <bitness>	- Bits per word (default: 32)\n"  "	-e <l|b>	- Endianess Little/Big (default: host)\n" +"	-o <file>	- Output to file (default: stdout)\n"  "\n"  "  Data:\n"  "	Data can be specified as sequence of hexdecimal number or\n" @@ -557,6 +567,38 @@ int WriteRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, cons      return 0;  } +int Grab(pcilib_t *handle, const char *output) { +    int err; +     +    void *data = NULL; +    size_t size, written; +     +    FILE *o; +     +    err = pcilib_grab(handle, PCILIB_ALL_EVENTS, &size, &data, NULL); +    if (err) { +	Error("Grabbing event is failed"); +    } + +    if (output) {     +	o = fopen(output, "w"); +	if (!o) { +	    Error("Failed to open file \"%s\"", output); +	} +	 +	printf("Writting %i bytes into %s...\n", size, output); +    } else o = stdout; +     +    written = fwrite(data, 1, size, o); +    if (written != size) { +	if (written > 0) Error("Write failed, only %z bytes out of %z are stored", written, size); +	else Error("Write failed"); +    } +     +    if (o != stdout) fclose(o); + +    return 0; +}  int main(int argc, char **argv) {      int i; @@ -571,16 +613,18 @@ int main(int argc, char **argv) {      const char *reg = NULL;      const char *bank = NULL;      char **data = NULL; +    const char *event = NULL;      uintptr_t start = -1;      size_t size = 1;      access_t access = 4;      int skip = 0;      int endianess = 0; +    const char *output = NULL;      pcilib_t *handle; -    while ((c = getopt_long(argc, argv, "hilpr::w::d:m:b:a:s:e:", long_options, NULL)) != (unsigned char)-1) { +    while ((c = getopt_long(argc, argv, "hilpr::w::d:m:b:a:s:e:g:", long_options, NULL)) != (unsigned char)-1) {  	extern int optind;  	switch (c) {  	    case OPT_HELP: @@ -596,6 +640,11 @@ int main(int argc, char **argv) {  		mode = MODE_LIST;  	    break; +	    case OPT_RESET: +		if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + +		mode = MODE_RESET; +	    break;  	    case OPT_BENCHMARK:  		if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); @@ -615,6 +664,13 @@ int main(int argc, char **argv) {  		if (optarg) addr = optarg;  		else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];  	    break; +	    case OPT_GRAB: +		if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + +		mode = MODE_GRAB; +		if (optarg) event = optarg; +		else if ((optind < argc)&&(argv[optind][0] != '-')) event = argv[optind++]; +	    break;  	    case OPT_DEVICE:  		fpga_device = optarg;  	    break; @@ -652,6 +708,9 @@ int main(int argc, char **argv) {  		} else Usage(argc, argv, "Invalid endianess is specified (%s)", optarg);  	    break; +	    case OPT_OUTPUT: +		output = optarg; +	    break;  	    default:  		Usage(argc, argv, "Unknown option (%s)", argv[optind]);  	} @@ -674,11 +733,22 @@ int main(int argc, char **argv) {          if (!addr) Usage(argc, argv, "The address is not specified");          if (((argc - optind) == 1)&&(*argv[optind] == '*')) {      	    int vallen = strlen(argv[optind]); -	    data = (char**)malloc(size * (vallen + sizeof(char*))); -	    if (!data) Error("Error allocating memory for data array"); -	    for (i = 0; i < size; i++) { -		data[i] = ((char*)data) + size * sizeof(char*) + i * vallen; -		strcpy(data[i], argv[optind] + 1); +    	    if (vallen > 1) { +		data = (char**)malloc(size * (vallen + sizeof(char*))); +		if (!data) Error("Error allocating memory for data array"); + +		for (i = 0; i < size; i++) { +		    data[i] = ((char*)data) + size * sizeof(char*) + i * vallen; +		    strcpy(data[i], argv[optind] + 1); +		} +	    } else { +		data = (char**)malloc(size * (9 + sizeof(char*))); +		if (!data) Error("Error allocating memory for data array"); +		 +		for (i = 0; i < size; i++) { +		    data[i] = ((char*)data) + size * sizeof(char*) + i * 9; +		    sprintf(data[i], "%x", i); +		}  	    }          } else if ((argc - optind) == size) data = argv + optind;          else Usage(argc, argv, "The %i data values is specified, but %i required", argc - optind, size); @@ -757,6 +827,12 @@ int main(int argc, char **argv) {          if (reg) WriteRegister(handle, model, bank, reg, data);  	else WriteRegisterRange(handle, model, bank, start, size, data);       break; +     case MODE_RESET: +        pcilib_reset(handle); +     break; +     case MODE_GRAB: +        Grab(handle, output); +     break;      }      pcilib_close(handle); @@ -19,6 +19,9 @@ CFLAGS += $(addprefix -I ,$(INCDIR)) -fPIC -std=c99  SRC = $(wildcard *.cpp)  SRCC = $(wildcard *.c) +SRC += $(wildcard ipecamera/*.cpp) +SRCC += $(wildcard ipecamera/*.c) +  # Corresponding object files   OBJ = $(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))  OBJ += $(addprefix $(OBJDIR)/,$(SRCC:.c=.o)) diff --git a/driver/base.c b/driver/base.c index c740856..b999cac 100644 --- a/driver/base.c +++ b/driver/base.c @@ -626,6 +626,7 @@ int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vm  	/* Check sizes */  	vma_size = (vmap->vm_end - vmap->vm_start); +  	if ((vma_size != bar_length) &&  	   ((bar_length < PAGE_SIZE) && (vma_size != PAGE_SIZE))) {  		mod_info( "mmap size is not correct! bar: %lu - vma: %lu\n", bar_length, vma_size ); @@ -12,6 +12,7 @@ enum {      PCILIB_ERROR_NOTSUPPORTED,      PCILIB_ERROR_NOTFOUND,      PCILIB_ERROR_OUTOFRANGE, +    PCILIB_ERROR_NOTINITIALIZED  } pcilib_errot_t; diff --git a/ipecamera.h b/ipecamera.h deleted file mode 100644 index 9061dea..0000000 --- a/ipecamera.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef _IPECAMERA_H -#define _IPECAMERA_H - -#include <stdio.h> - -#include "pcilib.h" - -#define IPECAMERA_REGISTER_SPACE 0xfeaffc00 -#define IPECAMERA_REGISTER_WRITE (IPECAMERA_REGISTER_SPACE + 0) -#define IPECAMERA_REGISTER_READ (IPECAMERA_REGISTER_WRITE + 4) - -#ifdef _IPECAMERA_C -pcilib_register_bank_description_t ipecamera_register_banks[] = { -    { PCILIB_REGISTER_BANK0, 128, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ,	IPECAMERA_REGISTER_WRITE, PCILIB_BIG_ENDIAN, 8, PCILIB_LITTLE_ENDIAN, "cmosis", "CMOSIS CMV2000 Registers" }, -    { PCILIB_REGISTER_BANK1, 64, PCILIB_DEFAULT_PROTOCOL, IPECAMERA_REGISTER_SPACE, IPECAMERA_REGISTER_SPACE, PCILIB_BIG_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "fpga", "IPECamera Registers" }, -    { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL } -}; - -pcilib_register_description_t ipecamera_registers[] = { -{1, 	16, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines",  ""}, -{3, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start1", ""}, -{5, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start2", ""}, -{7, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start3", ""}, -{9, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start4", ""}, -{11,	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start5", ""}, -{13, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start6", ""}, -{15, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start7", ""}, -{17, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start8", ""}, -{19, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines1", ""}, -{21, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines2", ""}, -{23, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines3", ""}, -{25, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines4", ""}, -{27, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines5", ""}, -{29, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines6", ""}, -{31, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines7", ""}, -{33, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines8", ""}, -{35, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_s", ""}, -{37, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_a", ""}, -{39, 	1, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "color", ""}, -{40, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "image_flipping", ""}, -{41, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_flags", ""}, -{42, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time", ""}, -{45, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step", ""}, -{48, 	24, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp1", ""}, -{51, 	24, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp2", ""}, -{54, 	2, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes", ""}, -{55, 	8, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq", ""}, -{56, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time2", ""}, -{59, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step2", ""}, -{68, 	2, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes2", ""}, -{69, 	8, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq2", ""}, -{70, 	16, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_frames", ""}, -{72, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "output_mode", ""}, -{78, 	12, 	85, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "training_pattern", ""}, -{80, 	18, 	0x3FFFF,PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "channel_en", ""}, -{89, 	8, 	96, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow2", ""}, -{90, 	8, 	96, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow3", ""}, -{100, 	14, 	16260, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "offset", ""}, -{102, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "pga", ""}, -{103, 	8, 	32, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_gain", ""}, -{111, 	1, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "bit_mode", ""}, -{112, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_resolution", ""}, -{126, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "temp", ""}, -{0,	32,	0,	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "spi_conf_input", ""}, -{1,	32,	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "spi_conf_output", ""}, -{2,	32,	0,	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "spi_clk_speed", ""}, -{3,	32,	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "firmware_version", ""}, -{6,	16,	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "cmosis_temperature", ""}, -{7,	32,	0,	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "temperature_sample_timing", ""}, -{0,	0,	0,	0,                  0,                     NULL, NULL} -}; - -pcilib_register_range_t ipecamera_register_ranges[] = { -    {0, 128, PCILIB_REGISTER_BANK0}, {0, 0, 0} -}; - -#else -extern pcilib_register_description_t ipecamera_registers[]; -extern pcilib_register_bank_description_t ipecamera_register_banks[]; -extern pcilib_register_range_t ipecamera_register_ranges[]; -#endif  - -int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value); -int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value); - -#endif /* _IPECAMERA_H */ diff --git a/ipecamera/image.c b/ipecamera/image.c new file mode 100644 index 0000000..e7661b2 --- /dev/null +++ b/ipecamera/image.c @@ -0,0 +1,287 @@ +#define _IPECAMERA_IMAGE_C +#define _BSD_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/time.h> +#include <assert.h> + +#include "../tools.h" +#include "../error.h" + +#include "pcilib.h" + +#include "model.h" +#include "image.h" + +#define IPECAMERA_SLEEP_TIME 250000 + +struct ipecamera_s { +    pcilib_t *pcilib; + +    char *data; +    size_t size; + +    pcilib_callback_t cb; +    void *cb_user; +     +    int width; +    int height; + +    pcilib_event_id_t event_id; + +    pcilib_register_t control_reg, status_reg; +    pcilib_register_t start_reg, end_reg; +    pcilib_register_t lines_reg; +    pcilib_register_t exposure_reg; + +    void *buffer;     +}; + + +#define FIND_REG(var, bank, name)  \ +        ctx->var = pcilib_find_register(pcilib, bank, name); \ +	if (ctx->var ==  PCILIB_REGISTER_INVALID) { \ +	    err = -1; \ +	    pcilib_error("Unable to find a %s register", name); \ +	} +     + +#define GET_REG(reg, var) \ +    err = pcilib_read_register_by_id(pcilib, ctx->reg, &var); \ +    if (err) { \ +	pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \ +	return err; \ +    } + +#define SET_REG(reg, val) \ +    err = pcilib_write_register_by_id(pcilib, ctx->reg, val); \ +    if (err) { \ +	pcilib_error("Error writting %s register", ipecamera_registers[ctx->reg].name); \ +	return err; \ +    } + +#define CHECK_REG(reg, check) \ +    err = pcilib_read_register_by_id(pcilib, ctx->reg, &value); \ +    if (err) { \ +	pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \ +	return err; \ +    } \ +    if (!(check)) { \ +	pcilib_error("Unexpected value (%li) of register %s", value, ipecamera_registers[ctx->reg].name); \ +	return err; \ +    } + + +void *ipecamera_init(pcilib_t *pcilib) { +    int err = 0;  +     +    ipecamera_t *ctx = malloc(sizeof(ipecamera_t)); + +    if (ctx) { +	ctx->pcilib = pcilib; + +	ctx->data = pcilib_resolve_data_space(pcilib, 0, &ctx->size); +	if (!ctx->data) { +	    err = -1; +	    pcilib_error("Unable to resolve the data space"); +	} +	 +	ctx->buffer = malloc(1088 * 2048 * 2); +	if (!ctx->buffer) { +	    err = -1; +	    pcilib_error("Unable to allocate ring buffer"); +	} +	 +	FIND_REG(status_reg, "fpga", "status"); +	FIND_REG(control_reg, "fpga", "control"); +	FIND_REG(start_reg, "fpga", "start_address"); +	FIND_REG(end_reg, "fpga", "end_address"); + +	FIND_REG(lines_reg, "cmosis", "number_lines"); +	FIND_REG(exposure_reg, "cmosis", "exp_time"); + +	if (err) { +	    free(ctx); +	    return NULL; +	} +    } +     +    return (void*)ctx; +} + +void ipecamera_free(void *vctx) { +    if (vctx) { +	ipecamera_t *ctx = (ipecamera_t*)vctx; +	 +	if (ctx->buffer) free(ctx->buffer); +	free(ctx); +    } +} + +int ipecamera_reset(void *vctx) { +    int err; +    pcilib_t *pcilib; +    ipecamera_t *ctx = (ipecamera_t*)vctx; + +    pcilib_register_t control, status; +    pcilib_register_value_t value; +     +    if (!ctx) { +	pcilib_error("IPECamera imaging is not initialized"); +	return PCILIB_ERROR_NOTINITIALIZED; +    } +     +    pcilib = ctx->pcilib; +    control = ctx->control_reg; +    status = ctx->status_reg; + +	// Set Reset bit to CMOSIS +    err = pcilib_write_register_by_id(pcilib, control, 5); +    if (err) { +	pcilib_error("Error setting CMOSIS reset bit"); +	return err; +    } +    usleep(IPECAMERA_SLEEP_TIME); + +	// Remove Reset bit to CMOSIS +    err = pcilib_write_register_by_id(pcilib, control, 1); +    if (err) { +	pcilib_error("Error reseting CMOSIS reset bit"); +	return err; +    } +    usleep(IPECAMERA_SLEEP_TIME); + +	// Special settings for CMOSIS v.2 +    value = 01; err = pcilib_write_register_space(pcilib, "cmosis", 115, 1, &value); +    if (err) { +	pcilib_error("Error setting CMOSIS configuration"); +	return err; +    } +    usleep(IPECAMERA_SLEEP_TIME); +     +    value = 07; err = pcilib_write_register_space(pcilib, "cmosis", 82, 1, &value); +    if (err) { +	pcilib_error("Error setting CMOSIS configuration"); +	return err; +    } +    usleep(IPECAMERA_SLEEP_TIME); + +	// This is temporary for verification purposes +    memset(ctx->data, 0, ctx->size); + +    err = pcilib_read_register_by_id(pcilib, status, &value); +    if (err) { +	pcilib_error("Error reading status register"); +	return err; +    } + +    if (value != 0x0849FFFF) { +	pcilib_error("Unexpected value (%lx) of status register", value); +	return PCILIB_ERROR_VERIFY; +    } + +    return 0;     +} + +int ipecamera_start(void *vctx, pcilib_event_t event_mask, pcilib_callback_t cb, void *user) { +    ipecamera_t *ctx = (ipecamera_t*)vctx; + +    if (!ctx) { +	pcilib_error("IPECamera imaging is not initialized"); +	return PCILIB_ERROR_NOTINITIALIZED; +    } +     +    ctx->cb = cb; +    ctx->cb_user = user; +     +     +    ctx->event_id = 0; +     +    ctx->width = 1270; +    ctx->height = 1088; //GET_REG(lines_reg, lines); + +    // allocate memory +     +    return 0; +} + + +int ipecamera_stop(void *vctx) { +    ipecamera_t *ctx = (ipecamera_t*)vctx; + +    if (!ctx) { +	pcilib_error("IPECamera imaging is not initialized"); +	return PCILIB_ERROR_NOTINITIALIZED; +    } +     +    return 0; +} + + +static int ipecamera_get_line(ipecamera_t *ctx, int line) { +    int err; +    pcilib_t *pcilib = ctx->pcilib; +    pcilib_register_value_t ptr, size, value; + +    ipecamera_reset((void*)ctx); + +    SET_REG(lines_reg, 1); +     +    SET_REG(control_reg, 149); +    usleep(IPECAMERA_SLEEP_TIME); +    CHECK_REG(status_reg, 0x0849FFFF); +     +    GET_REG(start_reg, ptr); +    GET_REG(end_reg, size); +    size -= ptr; + +    printf("%i: %i %i\n", line, ptr, size);     +     +    SET_REG(control_reg, 141); +    usleep(IPECAMERA_SLEEP_TIME); +    CHECK_REG(status_reg, 0x0849FFFF); +} + + +static int ipecamera_get_image(ipecamera_t *ctx) { +    int err; +    int i; +    pcilib_t *pcilib = ctx->pcilib; + +    for (i = 0; i < 1088; i++) { +	ipecamera_get_line(ctx, i); +    } +     +    ctx->event_id++; +} + + +int ipecamera_trigger(void *vctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) { +    int err; +    pcilib_t *pcilib; +    ipecamera_t *ctx = (ipecamera_t*)vctx; + +    if (!ctx) { +	pcilib_error("IPECamera imaging is not initialized"); +	return PCILIB_ERROR_NOTINITIALIZED; + +    } +     +    err = ipecamera_get_image(ctx); +    if (!err) err = ctx->cb(event, ctx->event_id, ctx->cb_user); + +    return err; +} + + +void* ipecamera_get(void *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) { +    if (size) *size = ctx->width * ctx->height * 2; +    return ctx->buffer; +} + +int ipecamera_return(void *ctx, pcilib_event_id_t event_id) { +    return 0; +} diff --git a/ipecamera/image.h b/ipecamera/image.h new file mode 100644 index 0000000..d174b95 --- /dev/null +++ b/ipecamera/image.h @@ -0,0 +1,22 @@ +#ifndef _IPECAMERA_IMAGE_H +#define _IPECAMERA_IMAGE_H + +#include <stdio.h> + +#include "pcilib.h" + +typedef struct ipecamera_s ipecamera_t; + +void *ipecamera_init(pcilib_t *pcilib); +void ipecamera_free(void *ctx); + +int ipecamera_reset(void *ctx); +int ipecamera_start(void *ctx, pcilib_event_t event_mask, pcilib_callback_t cb, void *user); +int ipecamera_stop(void *ctx); +int ipecamera_trigger(void *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data); + +void* ipecamera_get(void *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size); +int ipecamera_return(void *ctx, pcilib_event_id_t event_id); + + +#endif /* _IPECAMERA_IMAGE_H */ diff --git a/ipecamera/ipecamera.h b/ipecamera/ipecamera.h new file mode 100644 index 0000000..8b27516 --- /dev/null +++ b/ipecamera/ipecamera.h @@ -0,0 +1,6 @@ +#ifndef _IPECAMERA_H +#define _IPECAMERA_H + + + +#endif /* _IPECAMERA_H */ diff --git a/ipecamera.c b/ipecamera/model.c index 9c238f5..4e475b1 100644 --- a/ipecamera.c +++ b/ipecamera/model.c @@ -1,10 +1,10 @@ -#define _IPECAMERA_C +#define _IPECAMERA_MODEL_C  #include <sys/time.h>  #include <assert.h> -#include "tools.h" -#include "ipecamera.h" -#include "error.h" +#include "../tools.h" +#include "../error.h" +#include "model.h"  #define ADDR_MASK 0x7F00  #define WRITE_BIT 0x8000 @@ -110,6 +110,11 @@ retry:      }      if ((val & READ_READY_BIT) == 0) { +	if (--retries > 0) { +	    pcilib_warning("Timeout occured during register write, retrying (try %i of %i)...", RETRIES - retries, RETRIES); +	    goto retry; +	} +  	pcilib_error("Timeout writting register value");  	return PCILIB_ERROR_TIMEOUT;      } @@ -121,7 +126,7 @@ retry:      if (((val&ADDR_MASK) >> 8) != addr) {  	if (--retries > 0) { -	    pcilib_warning("Address verification failed during register read, retrying (try %i of %i)...", RETRIES - retries, RETRIES); +	    pcilib_warning("Address verification failed during register write, retrying (try %i of %i)...", RETRIES - retries, RETRIES);  	    goto retry;  	}  	pcilib_error("Address verification failed during register write"); @@ -137,3 +142,6 @@ retry:      return 0;  } + + + diff --git a/ipecamera/model.h b/ipecamera/model.h new file mode 100644 index 0000000..f3f46dd --- /dev/null +++ b/ipecamera/model.h @@ -0,0 +1,110 @@ +#ifndef _IPECAMERA_MODEL_H +#define _IPECAMERA_MODEL_H + +#include <stdio.h> + +#include "pcilib.h" +#include "image.h" + +#define IPECAMERA_REGISTER_SPACE 0xfeaffc00 +#define IPECAMERA_REGISTER_WRITE (IPECAMERA_REGISTER_SPACE + 0) +#define IPECAMERA_REGISTER_READ (IPECAMERA_REGISTER_WRITE + 4) + +#ifdef _IPECAMERA_MODEL_C +pcilib_register_bank_description_t ipecamera_register_banks[] = { +    { PCILIB_REGISTER_BANK0, 128, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ,	IPECAMERA_REGISTER_WRITE, PCILIB_BIG_ENDIAN, 8, PCILIB_LITTLE_ENDIAN, "cmosis", "CMOSIS CMV2000 Registers" }, +    { PCILIB_REGISTER_BANK1, 64, PCILIB_DEFAULT_PROTOCOL, IPECAMERA_REGISTER_SPACE, IPECAMERA_REGISTER_SPACE, PCILIB_BIG_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "fpga", "IPECamera Registers" }, +    { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL } +}; + +pcilib_register_description_t ipecamera_registers[] = { +{1, 	0, 	16, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines",  ""}, +{3, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start1", ""}, +{5, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start2", ""}, +{7, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start3", ""}, +{9, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start4", ""}, +{11,	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start5", ""}, +{13, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start6", ""}, +{15, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start7", ""}, +{17, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start8", ""}, +{19, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines1", ""}, +{21, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines2", ""}, +{23, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines3", ""}, +{25, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines4", ""}, +{27, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines5", ""}, +{29, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines6", ""}, +{31, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines7", ""}, +{33, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines8", ""}, +{35, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_s", ""}, +{37, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_a", ""}, +{39, 	0, 	1, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "color", ""}, +{40, 	0, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "image_flipping", ""}, +{41, 	0, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_flags", ""}, +{42, 	0, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time", ""}, +{45, 	0, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step", ""}, +{48, 	0, 	24, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp1", ""}, +{51, 	0, 	24, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp2", ""}, +{54, 	0, 	2, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes", ""}, +{55, 	0, 	8, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq", ""}, +{56, 	0, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time2", ""}, +{59, 	0, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step2", ""}, +{68, 	0, 	2, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes2", ""}, +{69, 	0, 	8, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq2", ""}, +{70, 	0, 	16, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_frames", ""}, +{72, 	0, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "output_mode", ""}, +{78, 	0, 	12, 	85, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "training_pattern", ""}, +{80, 	0, 	18, 	0x3FFFF,PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "channel_en", ""}, +{89, 	0, 	8, 	96, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow2", ""}, +{90, 	0, 	8, 	96, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow3", ""}, +{100, 	0, 	14, 	16260, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "offset", ""}, +{102, 	0, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "pga", ""}, +{103, 	0, 	8, 	32, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_gain", ""}, +{111, 	0, 	1, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "bit_mode", ""}, +{112, 	0, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_resolution", ""}, +{126, 	0, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "temp", ""}, +{0,	0, 	32,	0,	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "spi_conf_input", ""}, +{1,	0, 	32,	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "spi_conf_output", ""}, +{2,	0, 	32,	0,	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "spi_clk_speed", ""}, +{3,	0, 	32,	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "firmware_version", ""}, +{4,	0, 	32, 	0,	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "control", ""}, +{5,	0, 	32, 	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "status", ""}, +{6,	0, 	16,	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "cmosis_temperature", ""}, +{7,	0, 	32,	0,	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "temperature_sample_timing", ""}, +{8,	0, 	32, 	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "start_address", ""}, +{9,	0, 	32, 	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "end_address", ""}, +{10,	0, 	32, 	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "last_write_address", ""}, +{11,	0, 	32, 	0,	PCILIB_REGISTER_R,  PCILIB_REGISTER_BANK1, "last_write_value", ""}, +{0,	0,	0,	0,	0,                  0,                     NULL, NULL} +}; + +pcilib_register_range_t ipecamera_register_ranges[] = { +    {0, 128, PCILIB_REGISTER_BANK0}, {0, 0, 0} +}; + +#else +extern pcilib_register_description_t ipecamera_registers[]; +extern pcilib_register_bank_description_t ipecamera_register_banks[]; +extern pcilib_register_range_t ipecamera_register_ranges[]; +#endif  + +#ifdef _IPECAMERA_IMAGE_C +pcilib_event_api_description_t ipecamera_image_api = { +    ipecamera_init, +    ipecamera_free, + +    ipecamera_reset, +    ipecamera_start, +    ipecamera_stop, +    ipecamera_trigger, +     +    ipecamera_get, +    ipecamera_return +}; +#else +extern pcilib_event_api_description_t ipecamera_image_api; +#endif + +int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value); +int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value); + +#endif /* _IPECAMERA_MODEL_H */ @@ -1,4 +1,5 @@  #define _PCILIB_PCI_C +#define _POSIX_C_SOURCE 199309L  #include <stdio.h>  #include <string.h> @@ -17,7 +18,7 @@  #include "tools.h"  #include "pci.h" -#include "ipecamera.h" +#include "ipecamera/model.h"  #include "error.h"  #define BIT_MASK(bits) ((1l << (bits)) - 1) @@ -34,6 +35,12 @@ struct pcilib_s {      pcilib_bar_t reg_bar;      char *reg_space; + +    pcilib_bar_t data_bar; +    char *data_space; +    size_t data_size; +     +    void *event_ctx;  #ifdef PCILIB_FILE_IO      int file_io_handle; @@ -60,6 +67,7 @@ int pcilib_set_error_handler(void (*err)(const char *msg, ...), void (*warn)(con  }  pcilib_t *pcilib_open(const char *device, pcilib_model_t model) { +    pcilib_event_api_description_t *api;      pcilib_t *ctx = malloc(sizeof(pcilib_t));      if (ctx) { @@ -67,6 +75,10 @@ pcilib_t *pcilib_open(const char *device, pcilib_model_t model) {  	ctx->page_mask = (uintptr_t)-1;  	ctx->model = model;  	ctx->reg_space = NULL; + +	if (!model) model = pcilib_get_model(ctx); +	api = pcilib_model[model].event_api; +        if ((api)&&(api->init)) ctx->event_ctx = api->init(ctx);      }      return ctx; @@ -297,12 +309,67 @@ static int pcilib_map_register_space(pcilib_t *ctx) {  	    }  	} -	return -1; +	return PCILIB_ERROR_NOTFOUND;      }      return 0;  } + +static int pcilib_map_data_space(pcilib_t *ctx, uintptr_t addr) { +    int err; +    int i; +     +    if (!ctx->data_space) { +        const pci_board_info *board_info = pcilib_get_board_info(ctx); + +	err = pcilib_map_register_space(ctx); +	if (err) { +	    pcilib_error("Error mapping register space"); +	    return err; +	} +	 +	if (addr) { +	} +	 +	int data_bar = -1;	 +	 +	for (i = 0; i < PCILIB_MAX_BANKS; i++) { +	    if ((i == ctx->reg_bar)||(!board_info->bar_length[i])) continue; +	     +	    if (addr) { +	        if (board_info->bar_start[i] == addr) { +		    data_bar = i; +		    break; +		} +	    } else { +		if (data_bar >= 0) { +		    data_bar = -1; +		    break; +		} +		 +		data_bar = i; +	    } +	} + +	if (data_bar < 0) { +	    if (addr) pcilib_error("Unable to find the specified data space (%lx)", addr); +	    else pcilib_error("Unable to find the data space"); +	    return PCILIB_ERROR_NOTFOUND; +	} +	 +	ctx->data_bar = data_bar; +	ctx->data_space = pcilib_map_bar(ctx, data_bar); +	ctx->data_size = board_info->bar_length[data_bar]; +	 +	if (!ctx->data_space) { +	    pcilib_error("Unable to map the data space"); +	    return PCILIB_ERROR_FAILED; +	} +    } +     +    return 0; +}  static void pcilib_unmap_register_space(pcilib_t *ctx) {      if (ctx->reg_space) { @@ -311,6 +378,13 @@ static void pcilib_unmap_register_space(pcilib_t *ctx) {      }  } +static void pcilib_unmap_data_space(pcilib_t *ctx) { +    if (ctx->data_space) { +	pcilib_unmap_bar(ctx, ctx->data_bar, ctx->data_space); +	ctx->data_space = NULL; +    } +} +  char  *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr) {      size_t offset = addr - ctx->board_info.bar_start[ctx->reg_bar];      if (offset < ctx->board_info.bar_length[ctx->reg_bar]) { @@ -319,11 +393,31 @@ char  *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr) {      return NULL;  } +char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size) { +    int err; +     +    err = pcilib_map_data_space(ctx, addr); +    if (err) { +	pcilib_error("Failed to map the specified address space (%lx)", addr); +	return NULL; +    } +     +    if (size) *size = ctx->data_size;     +     +    return ctx->data_space + (ctx->board_info.bar_start[ctx->data_bar] & ctx->page_mask); +} +  void pcilib_close(pcilib_t *ctx) {      if (ctx) { +	pcilib_model_t model = pcilib_get_model(ctx); +	pcilib_event_api_description_t *api = pcilib_model[model].event_api; +     +        if ((api)&&(api->free)) api->free(ctx->event_ctx); +	if (ctx->data_space) pcilib_unmap_data_space(ctx);  	if (ctx->reg_space) pcilib_unmap_register_space(ctx);  	close(ctx->handle); +	  	free(ctx);      }  } @@ -491,17 +585,21 @@ int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_reg  	pcilib_error("Big-endian byte order support is not implemented");  	return PCILIB_ERROR_NOTSUPPORTED;      } else { -	for (i = 0, res = value; (res > 0)&&(i <= n); ++i) { -	    buf[i] = res & BIT_MASK(b->access); -	    res >>= b->access; -	} +	if (b->access == sizeof(res) * 8) { +	    buf[i] = res; +	} else { +	    for (i = 0, res = value; (res > 0)&&(i <= n); ++i) { +		buf[i] = res & BIT_MASK(b->access); +	        res >>= b->access; +	    } -	if (res) { -	    pcilib_error("Value %i is to big to fit in the register %s", value, r->name); -	    return PCILIB_ERROR_OUTOFRANGE; +	    if (res) { +		pcilib_error("Value %i is too big to fit in the register %s", value, r->name); +		return PCILIB_ERROR_OUTOFRANGE; +	    }  	}      } -     +      err = pcilib_write_register_space_internal(ctx, r->bank, r->addr, n, bits, buf);      return err;  } @@ -511,8 +609,175 @@ int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname,      int reg;      reg = pcilib_find_register(ctx, bank, regname); -    if (reg < 0) pcilib_error("Register (%s) is not found", regname); +    if (reg < 0) { +	pcilib_error("Register (%s) is not found", regname); +	return PCILIB_ERROR_NOTFOUND; +    }      return pcilib_write_register_by_id(ctx, reg, value);  } + +int pcilib_reset(pcilib_t *ctx) { +    pcilib_event_api_description_t *api; +     +    pcilib_model_t model = pcilib_get_model(ctx); + +    api = pcilib_model[model].event_api; +    if (!api) { +	pcilib_error("Event API is not supported by the selected model"); +	return PCILIB_ERROR_NOTSUPPORTED; +    } +     +    if (api->reset)  +	return api->reset(ctx->event_ctx); +	 +    return 0; +} + +int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, void *callback, void *user) { +    pcilib_event_api_description_t *api; +     +    pcilib_model_t model = pcilib_get_model(ctx); + +    api = pcilib_model[model].event_api; +    if (!api) { +	pcilib_error("Event API is not supported by the selected model"); +	return PCILIB_ERROR_NOTSUPPORTED; +    } + +    if (api->start)  +	return api->start(ctx->event_ctx, event_mask, callback, user); + +    return 0; +} + +int pcilib_stop(pcilib_t *ctx) { +    pcilib_event_api_description_t *api; +     +    pcilib_model_t model = pcilib_get_model(ctx); + +    api = pcilib_model[model].event_api; +    if (!api) { +	pcilib_error("Event API is not supported by the selected model"); +	return PCILIB_ERROR_NOTSUPPORTED; +    } + +    if (api->stop)  +	return api->stop(ctx->event_ctx); + +    return 0; +} + +int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) { +    pcilib_event_api_description_t *api; +     +    pcilib_model_t model = pcilib_get_model(ctx); + +    api = pcilib_model[model].event_api; +    if (!api) { +	pcilib_error("Event API is not supported by the selected model"); +	return PCILIB_ERROR_NOTSUPPORTED; +    } + +    if (api->trigger)  +	return api->trigger(ctx->event_ctx, event, trigger_size, trigger_data); + +    pcilib_error("Self triggering is not supported by the selected model"); +    return PCILIB_ERROR_NOTSUPPORTED; +} + + +void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) { +    pcilib_event_api_description_t *api = pcilib_model[ctx->model].event_api; +    if (!api) { +	pcilib_error("Event API is not supported by the selected model"); +	return NULL; +    } + +    if (api->get_data)  +	return api->get_data(ctx->event_ctx, event_id, data_type, size); + +    return NULL; +} + +int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id) { +    pcilib_event_api_description_t *api = pcilib_model[ctx->model].event_api; +    if (!api) { +	pcilib_error("Event API is not supported by the selected model"); +	return PCILIB_ERROR_NOTSUPPORTED; +    } + +    if (api->return_data)  +	return api->return_data(ctx->event_ctx, event_id); + +    return 0; +} + + +typedef struct { +    pcilib_t *ctx; +     +    size_t *size; +    void **data; +} pcilib_grab_callback_user_data_t; + +static int pcilib_grab_callback(pcilib_event_t event, pcilib_event_id_t event_id, void *vuser) { +    int err; +    void *data; +    size_t size; +    int allocated = 0; + +    pcilib_grab_callback_user_data_t *user = (pcilib_grab_callback_user_data_t*)vuser; + +    data = pcilib_get_data(user->ctx, event_id, PCILIB_EVENT_DATA, &size); +    if (!data) { +	pcilib_error("Error getting event data"); +	return PCILIB_ERROR_FAILED; +    } +     +    if (*(user->data)) { +	if ((user->size)&&(*(user->size) < size)) { +	    pcilib_error("The supplied buffer does not have enough space to hold the event data. Buffer size is %z, but %z is required", user->size, size); +	    return PCILIB_ERROR_MEMORY; +	} + +	*(user->size) = size; +    } else { +	*(user->data) = malloc(size); +	if (!*(user->data)) { +	    pcilib_error("Memory allocation (%i bytes) for event data is failed"); +	    return PCILIB_ERROR_MEMORY; +	} +	if (*(user->size)) *(user->size) = size; +	allocated = 1; +    } +     +    memcpy(*(user->data), data, size); +     +    err = pcilib_return_data(user->ctx, event_id); +    if (err) { +	if (allocated) { +	    free(*(user->data)); +	    *(user->data) = NULL; +	} +	pcilib_error("The event data had been overwritten before it was returned, data corruption may occur"); +	return err; +    } +     +    return 0; +} + +int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, const struct timespec *timeout) { +    int err; +     +    pcilib_grab_callback_user_data_t user = {ctx, size, data}; +     +    err = pcilib_start(ctx, event_mask, pcilib_grab_callback, &user); +    if (!err) { +	if (timeout) nanosleep(timeout, NULL); +        else err = pcilib_trigger(ctx, event_mask, 0, NULL); +    } +    pcilib_stop(ctx); +    return 0; +} @@ -11,13 +11,13 @@  const pci_board_info *pcilib_get_board_info(pcilib_t *ctx);  #ifdef _PCILIB_PCI_C -# include "ipecamera.h" +# include "ipecamera/model.h"  # include "default.h"  pcilib_model_description_t pcilib_model[3] = { -    { NULL, NULL, NULL }, -    { NULL, NULL, NULL }, -    { ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges } +    { NULL, NULL, NULL, NULL }, +    { NULL, NULL, NULL, NULL }, +    { ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges, &ipecamera_image_api }  };  pcilib_protocol_description_t pcilib_protocol[3] = { @@ -3,8 +3,16 @@  #define PCILIB_MAX_BANKS 6 +#include <time.h>  #include <stdint.h> +#ifndef __timespec_defined +struct timespec { +    time_t tv_sec; +    long tv_nsec; +}; +#endif /* __timespec_defined */ +  #define pcilib_memcpy pcilib_memcpy32  #define pcilib_datacpy pcilib_datacpy32 @@ -17,6 +25,9 @@ typedef uint8_t pcilib_register_bank_t;		/**< Type holding the register bank num  typedef uint8_t pcilib_register_bank_addr_t;	/**< Type holding the register bank number */  typedef uint8_t pcilib_register_size_t;		/**< Type holding the size in bits of the register */  typedef uint32_t pcilib_register_value_t;	/**< Type holding the register value */ +typedef uint64_t pcilib_event_id_t; + +typedef uint32_t pcilib_event_t;  typedef enum {      PCILIB_LITTLE_ENDIAN = 0, @@ -35,12 +46,15 @@ typedef enum {      PCILIB_REGISTER_RW = 3  } pcilib_register_mode_t; -  typedef enum {      PCILIB_DEFAULT_PROTOCOL,      IPECAMERA_REGISTER_PROTOCOL  } pcilib_register_protocol_t; +typedef enum { +    PCILIB_EVENT_DATA +} pcilib_event_data_type_t; +  #define PCILIB_BAR_DETECT 		((pcilib_bar_t)-1)  #define PCILIB_REGISTER_INVALID		((pcilib_register_t)-1)  #define PCILIB_ADDRESS_INVALID		((uintptr_t)-1) @@ -49,6 +63,7 @@ typedef enum {  #define PCILIB_REGISTER_BANK1 		1  #define PCILIB_REGISTER_BANK2 		2  #define PCILIB_REGISTER_BANK3 		3 +#define PCILIB_ALL_EVENTS		((pcilib_event_t)-1)  typedef struct {      pcilib_register_bank_addr_t addr; @@ -69,6 +84,7 @@ typedef struct {  typedef struct {      pcilib_register_addr_t addr; +    pcilib_register_size_t offset;      pcilib_register_size_t bits;      pcilib_register_value_t defvalue;      pcilib_register_mode_t mode; @@ -93,10 +109,28 @@ typedef struct {      int (*write)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value);  } pcilib_protocol_description_t; + +typedef int (*pcilib_callback_t)(pcilib_event_t event, pcilib_event_id_t event_id, void *user); + +typedef struct { +    void *(*init)(pcilib_t *ctx); +    void (*free)(void *ctx); + +    int (*reset)(void *ctx); + +    int (*start)(void *ctx, pcilib_event_t event_mask, pcilib_callback_t callback, void *user); +    int (*stop)(void *ctx); +    int (*trigger)(void *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data); +    void* (*get_data)(void *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size); +    int (*return_data)(void *ctx, pcilib_event_id_t event_id); +} pcilib_event_api_description_t; +  typedef struct {      pcilib_register_description_t *registers;      pcilib_register_bank_description_t *banks;      pcilib_register_range_t *ranges; +     +    pcilib_event_api_description_t *event_api;  } pcilib_model_description_t;  #ifndef _PCILIB_PCI_C @@ -112,7 +146,8 @@ void pcilib_close(pcilib_t *ctx);  void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar);  void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data); -char  *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr); +char *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr); +char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size);  pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank);  pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg); @@ -127,4 +162,24 @@ int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_reg  int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value);  int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value); +int pcilib_reset(pcilib_t *ctx); +int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, void *callback, void *user); +int pcilib_stop(pcilib_t *ctx); + +int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data); + +void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size); +/* + * This function is provided to find potentially corrupted data. If the data is overwritten by  + * the time return_data is called it will return error. + */ +int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id); + +/* + * @param data - will be allocated and shuld be freed if NULL, otherwise used and size should contain correct size. + *   In case of failure the content of data is undefined. + * @param timeout - will be autotriggered if NULL + */ +int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, const struct timespec *timeout); +  #endif /* _PCITOOL_PCILIB_H */ | 
