diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-04-12 20:57:41 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-04-12 20:57:41 +0200 |
commit | 445d5db0183cf5dc98a33160857f22f012cacea6 (patch) | |
tree | 24a86dc05195546cf888c104e604da9eb77b3309 | |
parent | 39b33ce4be920b19a6b0f694febf8609ae64512b (diff) | |
download | ipecamera-445d5db0183cf5dc98a33160857f22f012cacea6.tar.gz ipecamera-445d5db0183cf5dc98a33160857f22f012cacea6.tar.bz2 ipecamera-445d5db0183cf5dc98a33160857f22f012cacea6.tar.xz ipecamera-445d5db0183cf5dc98a33160857f22f012cacea6.zip |
Prototype of IPECamera image protocol
-rw-r--r-- | cli.c | 14 | ||||
-rw-r--r-- | error.h | 2 | ||||
-rw-r--r-- | ipecamera/image.c | 318 | ||||
-rw-r--r-- | ipecamera/image.h | 3 | ||||
-rw-r--r-- | ipecamera/ipecamera.h | 17 | ||||
-rw-r--r-- | ipecamera/model.h | 6 | ||||
-rw-r--r-- | pci.c | 37 | ||||
-rw-r--r-- | pci.h | 6 | ||||
-rw-r--r-- | pcilib.h | 23 | ||||
-rw-r--r-- | tools.c | 4 |
10 files changed, 364 insertions, 66 deletions
@@ -79,7 +79,7 @@ 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 }, + {"output", required_argument, 0, OPT_OUTPUT }, {"info", no_argument, 0, OPT_INFO }, {"list", no_argument, 0, OPT_LIST }, {"reset", no_argument, 0, OPT_RESET }, @@ -567,7 +567,7 @@ int WriteRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, cons return 0; } -int Grab(pcilib_t *handle, const char *output) { +int Grab(pcilib_t *handle, const char *event, const char *output) { int err; void *data = NULL; @@ -575,12 +575,14 @@ int Grab(pcilib_t *handle, const char *output) { FILE *o; - err = pcilib_grab(handle, PCILIB_ALL_EVENTS, &size, &data, NULL); + // ignoring event for now + + err = pcilib_grab(handle, PCILIB_EVENTS_ALL, &size, &data, NULL); if (err) { Error("Grabbing event is failed"); } - if (output) { + if (output) { o = fopen(output, "w"); if (!o) { Error("Failed to open file \"%s\"", output); @@ -624,7 +626,7 @@ int main(int argc, char **argv) { pcilib_t *handle; - while ((c = getopt_long(argc, argv, "hilpr::w::d:m:b:a:s:e:g:", long_options, NULL)) != (unsigned char)-1) { + while ((c = getopt_long(argc, argv, "hilpr::w::g::d:m:b:a:s:e:o:", long_options, NULL)) != (unsigned char)-1) { extern int optind; switch (c) { case OPT_HELP: @@ -831,7 +833,7 @@ int main(int argc, char **argv) { pcilib_reset(handle); break; case MODE_GRAB: - Grab(handle, output); + Grab(handle, event, output); break; } @@ -6,12 +6,14 @@ enum { PCILIB_ERROR_MEMORY, PCILIB_ERROR_INVALID_ADDRESS, PCILIB_ERROR_INVALID_BANK, + PCILIB_ERROR_INVALID_DATA, PCILIB_ERROR_TIMEOUT, PCILIB_ERROR_FAILED, PCILIB_ERROR_VERIFY, PCILIB_ERROR_NOTSUPPORTED, PCILIB_ERROR_NOTFOUND, PCILIB_ERROR_OUTOFRANGE, + PCILIB_ERROR_NOTAVAILABLE, PCILIB_ERROR_NOTINITIALIZED } pcilib_errot_t; diff --git a/ipecamera/image.c b/ipecamera/image.c index e7661b2..8899627 100644 --- a/ipecamera/image.c +++ b/ipecamera/image.c @@ -17,6 +17,10 @@ #include "image.h" #define IPECAMERA_SLEEP_TIME 250000 +#define IPECAMERA_MAX_LINES 1088 +#define IPECAMERA_DEFAULT_BUFFER_SIZE 10 + +typedef uint32_t ipecamera_payload_t; struct ipecamera_s { pcilib_t *pcilib; @@ -26,25 +30,30 @@ struct ipecamera_s { 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 n_lines_reg, line_reg; pcilib_register_t exposure_reg; - void *buffer; + int buffer_size; + int buf_ptr; + + int width, height; + + ipecamera_pixel_t *buffer; + ipecamera_change_mask_t *cmask; + + ipecamera_image_dimensions_t dim; }; #define FIND_REG(var, bank, name) \ ctx->var = pcilib_find_register(pcilib, bank, name); \ if (ctx->var == PCILIB_REGISTER_INVALID) { \ - err = -1; \ + err = PCILIB_ERROR_NOTFOUND; \ pcilib_error("Unable to find a %s register", name); \ } @@ -53,25 +62,36 @@ struct ipecamera_s { 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; \ + if (!err) { \ + err = pcilib_read_register_by_id(pcilib, ctx->reg, &value); \ + if (err) { \ + pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \ + } \ + if (!(check)) { \ + pcilib_error("Unexpected value (%li) of register %s", value, ipecamera_registers[ctx->reg].name); \ + err = PCILIB_ERROR_INVALID_DATA; \ + } \ + } + +#define CHECK_VALUE(value, val) \ + if ((!err)&&(value != val)) { \ + pcilib_error("Unexpected value (%x) in data stream (%x is expected)", value, val); \ + err = PCILIB_ERROR_INVALID_DATA; \ + } + +#define CHECK_FLAG(flag, check, ...) \ + if ((!err)&&(!(check))) { \ + pcilib_error("Unexpected value (%x) of " flag, __VA_ARGS__); \ + err = PCILIB_ERROR_INVALID_DATA; \ } @@ -81,26 +101,26 @@ void *ipecamera_init(pcilib_t *pcilib) { ipecamera_t *ctx = malloc(sizeof(ipecamera_t)); if (ctx) { + memset(ctx, 0, sizeof(ipecamera_t)); + ctx->pcilib = pcilib; + ctx->buffer_size = IPECAMERA_DEFAULT_BUFFER_SIZE; + ctx->dim.bpp = sizeof(ipecamera_pixel_t) * 8; + 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(n_lines_reg, "cmosis", "number_lines"); + FIND_REG(line_reg, "cmosis", "start1"); FIND_REG(exposure_reg, "cmosis", "exp_time"); if (err) { @@ -115,8 +135,7 @@ void *ipecamera_init(pcilib_t *pcilib) { void ipecamera_free(void *vctx) { if (vctx) { ipecamera_t *ctx = (ipecamera_t*)vctx; - - if (ctx->buffer) free(ctx->buffer); + ipecamera_stop(ctx); free(ctx); } } @@ -169,6 +188,14 @@ int ipecamera_reset(void *vctx) { } usleep(IPECAMERA_SLEEP_TIME); + + // Set default parameters + SET_REG(n_lines_reg, 1); + SET_REG(exposure_reg, 0); + SET_REG(control_reg, 141); + + if (err) return err; + // This is temporary for verification purposes memset(ctx->data, 0, ctx->size); @@ -187,6 +214,7 @@ int ipecamera_reset(void *vctx) { } int ipecamera_start(void *vctx, pcilib_event_t event_mask, pcilib_callback_t cb, void *user) { + int err = 0; ipecamera_t *ctx = (ipecamera_t*)vctx; if (!ctx) { @@ -197,13 +225,28 @@ int ipecamera_start(void *vctx, pcilib_event_t event_mask, pcilib_callback_t cb, ctx->cb = cb; ctx->cb_user = user; - ctx->event_id = 0; - - ctx->width = 1270; - ctx->height = 1088; //GET_REG(lines_reg, lines); + ctx->buf_ptr = 0; + + ctx->dim.width = 1270; + ctx->dim.height = 1088; //GET_REG(lines_reg, lines); + + ctx->buffer = malloc(ctx->dim.width * ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_pixel_t)); + if (!ctx->buffer) { + err = PCILIB_ERROR_MEMORY; + pcilib_error("Unable to allocate ring buffer"); + } - // allocate memory + ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t)); + if (!ctx->cmask) { + err = PCILIB_ERROR_MEMORY; + pcilib_error("Unable to allocate change-mask buffer"); + } + + if (err) { + ipecamera_stop(ctx); + return err; + } return 0; } @@ -216,19 +259,87 @@ int ipecamera_stop(void *vctx) { pcilib_error("IPECamera imaging is not initialized"); return PCILIB_ERROR_NOTINITIALIZED; } + + if (ctx->buffer) { + free(ctx->buffer); + ctx->buffer = NULL; + } + + if (ctx->cmask) { + free(ctx->cmask); + ctx->cmask = NULL; + } + + + ctx->event_id = 0; + ctx->buf_ptr = 0; return 0; } -static int ipecamera_get_line(ipecamera_t *ctx, int line) { - int err; +static int ipecamera_get_payload(ipecamera_t *ctx, ipecamera_pixel_t *pbuf, ipecamera_change_mask_t *cbuf, int line_req, pcilib_register_value_t size, ipecamera_payload_t *payload, pcilib_register_value_t *advance) { + int i, j; + int err = 0; + + ipecamera_payload_t info = payload[0]; + int channel = info&0x0F; // 4 bits + int line = (info>>4)&0x7FF; // 11 bits + // 1 bit is reserved + int bpp = (info>>16)&0x0F; // 4 bits + int pixels = (info>>20)&0xFF; // 8 bits + // 2 bits are reserved + int header = (info>>30)&0x03; // 2 bits + + int bytes; + + CHECK_FLAG("payload header magick", header == 2, header); + CHECK_FLAG("pixel size, only 10 bits are supported", bpp == 10, bpp); + //CHECK_FLAG("row number, should be %li", line == line_req, line, line_req); + CHECK_FLAG("relative row number, should be 0", line == 0, line); + CHECK_FLAG("channel, limited by 10 channels now", channel < 10, channel); + CHECK_FLAG("channel, dublicate entry for channel", ((*cbuf)&(1<<channel)) == 0, channel); + CHECK_FLAG("number of pixels, 127 is expected", pixels == 127, pixels); + + bytes = pixels / 3; + if (bytes * 3 < pixels) ++bytes; + + CHECK_FLAG("payload data bytes, at least %i are expected", bytes < size, size, bytes); + + for (i = 0; i < bytes; i++) { + ipecamera_payload_t data = payload[i + 1]; + int header = (data>>30)&0x03; + + CHECK_FLAG("payload data magick", header == 3, header); + + for (j = 0; j < 3; j++) { + int pix = 3 * i + j; + + if (pix == pixels) break; + + pbuf[channel*pixels + pix] = (data >> (10 * j))&0x3FF; + } + } + + if (!err) { + *cbuf |= (1 << channel); + *advance = bytes + 1; + } + + return err; +} + +static int ipecamera_get_line(ipecamera_t *ctx, ipecamera_pixel_t *pbuf, ipecamera_change_mask_t *cbuf, int line) { + int err = 0; pcilib_t *pcilib = ctx->pcilib; - pcilib_register_value_t ptr, size, value; + pcilib_register_value_t ptr, size, pos, advance, value; + ipecamera_payload_t *linebuf; + int column = 0; ipecamera_reset((void*)ctx); - SET_REG(lines_reg, 1); + SET_REG(n_lines_reg, 1); + SET_REG(line_reg, line); SET_REG(control_reg, 149); usleep(IPECAMERA_SLEEP_TIME); @@ -238,24 +349,74 @@ static int ipecamera_get_line(ipecamera_t *ctx, int line) { GET_REG(end_reg, size); size -= ptr; - printf("%i: %i %i\n", line, ptr, size); + pcilib_warning("Reading line %i: %i %i\n", line, ptr, size); + + if (size < 6) { + pcilib_error("The payload is tool small, we should have at least 5 header dwords and 1 footer."); + return PCILIB_ERROR_INVALID_DATA; + } - SET_REG(control_reg, 141); - usleep(IPECAMERA_SLEEP_TIME); - CHECK_REG(status_reg, 0x0849FFFF); + linebuf = (uint32_t*)malloc(size * sizeof(ipecamera_payload_t)); + if (linebuf) { + //pcilib_memcpy(linebuf, ctx->data + ptr, size * sizeof(ipecamera_payload_t)); + pcilib_datacpy(linebuf, ctx->data + ptr, sizeof(ipecamera_payload_t), size, pcilib_model[PCILIB_MODEL_IPECAMERA].endianess); + + + CHECK_VALUE(linebuf[0], 0x51111111); + CHECK_VALUE(linebuf[1], 0x52222222); + CHECK_VALUE(linebuf[2], 0x53333333); + CHECK_VALUE(linebuf[3], 0x54444444); + CHECK_VALUE(linebuf[4], 0x55555555); + + if (err) { + size = 0; + } else { + pos = 5; + size -= 6; + } + + while (size > 0) { + err = ipecamera_get_payload(ctx, pbuf, cbuf, line, size, linebuf + pos, &advance); + if (err) break; + + pos += advance; + size -= advance; + } + + CHECK_VALUE(linebuf[pos], 0x0AAAAAAA); + + CHECK_FLAG("payloads changed, we expect exactly 10 channels", *cbuf == 0x3FF, *cbuf); + + free(linebuf); + } + + if (!err) { + SET_REG(control_reg, 141); + usleep(IPECAMERA_SLEEP_TIME); + CHECK_REG(status_reg, 0x0849FFFF); + } + + return err; } static int ipecamera_get_image(ipecamera_t *ctx) { int err; int i; + int buf_ptr; pcilib_t *pcilib = ctx->pcilib; + +//atomic + buf_ptr = ctx->buf_ptr; + if (ctx->buf_ptr++ == ctx->buffer_size) ctx->buf_ptr = 0; + if (ctx->event_id++ == 0) ctx->event_id = 1; - for (i = 0; i < 1088; i++) { - ipecamera_get_line(ctx, i); + memset(ctx->buffer + buf_ptr * ctx->dim.width * ctx->dim.height, 0, ctx->dim.width * ctx->dim.height * sizeof(ipecamera_pixel_t)); + memset(ctx->cmask + buf_ptr * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t)); + + for (i = 0; i < ctx->dim.height; i++) { + ipecamera_get_line(ctx, ctx->buffer + buf_ptr * ctx->dim.width * ctx->dim.height + i * ctx->dim.width, ctx->cmask + buf_ptr * ctx->dim.height + i, i); } - - ctx->event_id++; } @@ -267,7 +428,6 @@ int ipecamera_trigger(void *vctx, pcilib_event_t event, size_t trigger_size, voi if (!ctx) { pcilib_error("IPECamera imaging is not initialized"); return PCILIB_ERROR_NOTINITIALIZED; - } err = ipecamera_get_image(ctx); @@ -276,12 +436,74 @@ int ipecamera_trigger(void *vctx, pcilib_event_t event, size_t trigger_size, voi return err; } +static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) { + int buf_ptr, diff; + + if ((!evid)||(evid > ctx->event_id)) return -1; + + diff = ctx->event_id - evid; + buf_ptr = ctx->buf_ptr - diff - 1; + if (buf_ptr < 0) { + buf_ptr += ctx->buffer_size; + if (buf_ptr < 0) return -1; + } + + return buf_ptr; +} + +void* ipecamera_get(void *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size) { + int buf_ptr; + ipecamera_t *ctx = (ipecamera_t*)vctx; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return NULL; + } + + + buf_ptr = ipecamera_resolve_event_id(ctx, event_id); -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; + //printf("%i %i %i\n", ctx->event_id, event_id, buf_ptr); + + if (buf_ptr < 0) return NULL; + + switch ((ipecamera_data_type_t)data_type) { + case IPECAMERA_IMAGE_DATA: + if (size) *size = ctx->dim.width * ctx->dim.height * sizeof(ipecamera_pixel_t); + return ctx->buffer + buf_ptr * ctx->dim.width * ctx->dim.height; + case IPECAMERA_CHANGE_MASK: + if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t); + return ctx->cmask + buf_ptr * ctx->dim.height; + case IPECAMERA_DIMENSIONS: + if (size) *size = sizeof(ipecamera_image_dimensions_t); + return &ctx->dim; + case IPECAMERA_IMAGE_REGION: + case IPECAMERA_PACKED_IMAGE: + // Shall we return complete image or only changed parts? + case IPECAMERA_PACKED_LINE: + case IPECAMERA_PACKED_PAYLOAD: + pcilib_error("Support for data type (%li) is not implemented yet", data_type); + return NULL; + default: + pcilib_error("Unknown data type (%li) is requested", data_type); + return NULL; + } } -int ipecamera_return(void *ctx, pcilib_event_id_t event_id) { + + +int ipecamera_return(void *vctx, pcilib_event_id_t event_id) { + ipecamera_t *ctx = (ipecamera_t*)vctx; + + if (!ctx) { + pcilib_error("IPECamera imaging is not initialized"); + return PCILIB_ERROR_NOTINITIALIZED; + + } + + if (ipecamera_resolve_event_id(ctx, event_id) < 0) { + return PCILIB_ERROR_NOTAVAILABLE; + } + return 0; } diff --git a/ipecamera/image.h b/ipecamera/image.h index d174b95..ede964c 100644 --- a/ipecamera/image.h +++ b/ipecamera/image.h @@ -3,6 +3,7 @@ #include <stdio.h> +#include "ipecamera.h" #include "pcilib.h" typedef struct ipecamera_s ipecamera_t; @@ -15,7 +16,7 @@ int ipecamera_start(void *ctx, pcilib_event_t event_mask, pcilib_callback_t cb, 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); +void* ipecamera_get(void *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size); int ipecamera_return(void *ctx, pcilib_event_id_t event_id); diff --git a/ipecamera/ipecamera.h b/ipecamera/ipecamera.h index 8b27516..d54dda2 100644 --- a/ipecamera/ipecamera.h +++ b/ipecamera/ipecamera.h @@ -1,6 +1,23 @@ #ifndef _IPECAMERA_H #define _IPECAMERA_H +typedef struct { + int bpp; /*<< Bits per pixel (8, 16, or 32) as returned by IPECAMERA_IMAGE_DATA */ + int real_bpp; /*<< Bits per pixel as returned by camera and IPECAMERA_PACKED_IMAGE */ + int width, height; +} ipecamera_image_dimensions_t; +typedef enum { + IPECAMERA_IMAGE_DATA = 0, + IPECAMERA_DIMENSIONS = 0x8000, + IPECAMERA_IMAGE_REGION = 0x8010, + IPECAMERA_PACKED_IMAGE = 0x8020, + IPECAMERA_PACKED_LINE = 0x8021, + IPECAMERA_PACKED_PAYLOAD = 0x8022, + IPECAMERA_CHANGE_MASK = 0x8030 +} ipecamera_data_type_t; + +typedef uint16_t ipecamera_change_mask_t; +typedef uint16_t ipecamera_pixel_t; #endif /* _IPECAMERA_H */ diff --git a/ipecamera/model.h b/ipecamera/model.h index f3f46dd..a7b7935 100644 --- a/ipecamera/model.h +++ b/ipecamera/model.h @@ -81,10 +81,16 @@ pcilib_register_range_t ipecamera_register_ranges[] = { {0, 128, PCILIB_REGISTER_BANK0}, {0, 0, 0} }; +pcilib_event_description_t ipecamera_events[] = { + {"new_frame", ""}, + {NULL, NULL} +}; + #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[]; +extern pcilib_event_description_t ipecamera_events[]; #endif #ifdef _IPECAMERA_IMAGE_C @@ -11,6 +11,7 @@ #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> +#include <arpa/inet.h> #include <errno.h> #include <assert.h> @@ -279,10 +280,25 @@ pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const ch if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; } - return -1; + return (pcilib_register_t)-1; }; +pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event) { + int i; + pcilib_register_bank_t res; + unsigned long addr; + + pcilib_model_t model = pcilib_get_model(ctx); + pcilib_event_description_t *events = pcilib_model[model].events; + + for (i = 0; events[i].name; i++) { + if (!strcasecmp(events[i].name, event)) return (1<<i); + } + + return (pcilib_event_t)-1; +} + static int pcilib_map_register_space(pcilib_t *ctx) { if (!ctx->reg_space) { @@ -484,7 +500,7 @@ int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_regi pcilib_register_value_t buf[n + 1]; err = pcilib_read_register_space_internal(ctx, r->bank, r->addr, n, bits, buf); - if (b->endianess) { + if ((b->endianess == PCILIB_BIG_ENDIAN)||((b->endianess == PCILIB_HOST_ENDIAN)&&(ntohs(1) == 1))) { pcilib_error("Big-endian byte order support is not implemented"); return PCILIB_ERROR_NOTSUPPORTED; } else { @@ -581,7 +597,7 @@ int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_reg pcilib_register_value_t buf[n + 1]; memset(buf, 0, (n + 1) * sizeof(pcilib_register_value_t)); - if (b->endianess) { + if ((b->endianess == PCILIB_BIG_ENDIAN)||((b->endianess == PCILIB_HOST_ENDIAN)&&(ntohs(1) == 1))) { pcilib_error("Big-endian byte order support is not implemented"); return PCILIB_ERROR_NOTSUPPORTED; } else { @@ -688,6 +704,19 @@ int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, voi } +void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, 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, arg_size, arg, size); + + return NULL; +} + 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) { @@ -696,7 +725,7 @@ void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_da } if (api->get_data) - return api->get_data(ctx->event_ctx, event_id, data_type, size); + return api->get_data(ctx->event_ctx, event_id, data_type, 0, NULL, size); return NULL; } @@ -15,9 +15,9 @@ const pci_board_info *pcilib_get_board_info(pcilib_t *ctx); # include "default.h" pcilib_model_description_t pcilib_model[3] = { - { NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL }, - { ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges, &ipecamera_image_api } + { 4, PCILIB_HOST_ENDIAN, NULL, NULL, NULL, NULL }, + { 4, PCILIB_HOST_ENDIAN, NULL, NULL, NULL, NULL }, + { 4, PCILIB_BIG_ENDIAN, ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges, ipecamera_events, &ipecamera_image_api } }; pcilib_protocol_description_t pcilib_protocol[3] = { @@ -30,7 +30,8 @@ typedef uint64_t pcilib_event_id_t; typedef uint32_t pcilib_event_t; typedef enum { - PCILIB_LITTLE_ENDIAN = 0, + PCILIB_HOST_ENDIAN = 0, + PCILIB_LITTLE_ENDIAN, PCILIB_BIG_ENDIAN } pcilib_endianess_t; @@ -63,7 +64,12 @@ 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) +#define PCILIB_EVENT0 1 +#define PCILIB_EVENT1 2 +#define PCILIB_EVENT2 4 +#define PCILIB_EVENT3 8 +#define PCILIB_EVENTS_ALL ((pcilib_event_t)-1) +#define PCILIB_EVENT_INVALID ((pcilib_event_t)-1) typedef struct { pcilib_register_bank_addr_t addr; @@ -105,6 +111,11 @@ typedef struct { } pcilib_register_range_t; typedef struct { + const char *name; + const char *description; +} pcilib_event_description_t; + +typedef struct { int (*read)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value); 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; @@ -121,14 +132,18 @@ typedef struct { 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); + void* (*get_data)(void *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size); int (*return_data)(void *ctx, pcilib_event_id_t event_id); } pcilib_event_api_description_t; typedef struct { + uint8_t access; + uint8_t endianess; + pcilib_register_description_t *registers; pcilib_register_bank_description_t *banks; pcilib_register_range_t *ranges; + pcilib_event_description_t *events; pcilib_event_api_description_t *event_api; } pcilib_model_description_t; @@ -151,6 +166,7 @@ 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); +pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event); int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf); int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf); @@ -169,6 +185,7 @@ 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); +void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, 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. @@ -196,7 +196,9 @@ void *pcilib_datacpy32(void * dst, void const * src, uint8_t size, size_t n, pci uint32_t * plDst = (uint32_t *) dst; uint32_t const * plSrc = (uint32_t const *) src; - int swap = (endianess == PCILIB_BIG_ENDIAN)?(ntohs(1)!=1):(ntohs(1)==1); + int swap = 0; + + if (endianess) swap = (endianess == PCILIB_BIG_ENDIAN)?(ntohs(1)!=1):(ntohs(1)==1); assert(size == 4); // only 32 bit at the moment |