diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-03-08 22:46:14 +0100 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-03-08 22:46:14 +0100 |
commit | 7f97ea07417de4c2ea260e2860e589011c732e04 (patch) | |
tree | 5e5dd32f4615a40990f8daf10a96f82f39ca3b83 /ipecamera.c | |
parent | 8a33c993a5771b041b67c365378ac40f76365da7 (diff) | |
download | ipecamera-7f97ea07417de4c2ea260e2860e589011c732e04.tar.gz ipecamera-7f97ea07417de4c2ea260e2860e589011c732e04.tar.bz2 ipecamera-7f97ea07417de4c2ea260e2860e589011c732e04.tar.xz ipecamera-7f97ea07417de4c2ea260e2860e589011c732e04.zip |
Initial support of IPECamera protocol
Diffstat (limited to 'ipecamera.c')
-rw-r--r-- | ipecamera.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/ipecamera.c b/ipecamera.c index b51a2f8..81cf7d7 100644 --- a/ipecamera.c +++ b/ipecamera.c @@ -1,4 +1,157 @@ #define _IPECAMERA_C +#include <sys/time.h> +#include <assert.h> + +#include "tools.h" #include "ipecamera.h" +#include "error.h" + +#define ADDR_MASK 0x7F00 +#define WRITE_BIT 0x8000 +#define RETRIES 10 + +#define READ_READY_BIT 0x20000 +#define READ_ERROR_BIT 0x40000 + +#define ipecamera_datacpy(dst, src, bank) pcilib_datacpy(dst, src, 4, 1, bank->raw_endianess) + +/* +int ipecamera_read_register_space(int handle, pcilib_model_t model, pcilib_register_t addr, pcilib_register_value_t *value) { + //ipelib_write_ + //(void *buf, int handle, pcilib_bar_t bar, uintptr_t addr, size_t size); + +} + +int ipecamera_write_register_space(int handle, pcilib_model_t model, pcilib_register_t addr, pcilib_register_value_t value) { +} + + +static int ipecamera_read_byte(int handle, int reg, int bits, uint8_t *value) { +} + +static int ipecamera_write_byte(int handle, int reg, int bits, uint8_t value) { +} +*/ + +static pcilib_register_value_t ipecamera_bit_mask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; + +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) { + uint32_t val; + char *wr, *rd; + struct timeval start, cur; + int retries = RETRIES; + + assert(addr < 128); + + wr = pcilib_resolve_register_address(ctx, bank->write_addr); + rd = pcilib_resolve_register_address(ctx, bank->read_addr); + if ((!rd)||(!wr)) { + pcilib_error("Error resolving addresses of read & write registers"); + return PCILIB_ERROR_INVALID_ADDRESS; + } + +retry: + val = (addr << 8); + + //printf("%i %x %p %p\n", addr, val, wr, rd); + + ipecamera_datacpy(wr, &val, bank); + + gettimeofday(&start, NULL); + + ipecamera_datacpy(&val, rd, bank); + while ((val & READ_READY_BIT) == 0) { + gettimeofday(&cur, NULL); + if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > PCILIB_REGISTER_TIMEOUT) break; + + ipecamera_datacpy(&val, rd, bank); + } + + if ((val & READ_READY_BIT) == 0) { + pcilib_error("Timeout reading register value"); + return PCILIB_ERROR_TIMEOUT; + } + + if (val & READ_ERROR_BIT) { + pcilib_error("Error reading register value"); + return PCILIB_ERROR_FAILED; + } + + 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); + goto retry; + } + pcilib_error("Address verification failed during register read"); + return PCILIB_ERROR_VERIFY; + } + + +// printf("%i\n", val&ipecamera_bit_mask[bits]); + + *value = val&ipecamera_bit_mask[bits]; + + return 0; +} + +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) { + uint32_t val; + char *wr, *rd; + struct timeval start, cur; + int retries = RETRIES; + + assert(addr < 128); + assert(value < 256); + + wr = pcilib_resolve_register_address(ctx, bank->write_addr); + rd = pcilib_resolve_register_address(ctx, bank->read_addr); + if ((!rd)||(!wr)) { + pcilib_error("Error resolving addresses of read & write registers"); + return PCILIB_ERROR_INVALID_ADDRESS; + } + +retry: + val = WRITE_BIT|(addr << 8)|(value&0xFF); + + //printf("%i %x %p %p\n", addr, val, wr, rd); + + ipecamera_datacpy(wr, &val, bank); + + gettimeofday(&start, NULL); + + ipecamera_datacpy(&val, rd, bank); + while ((val & READ_READY_BIT) == 0) { + gettimeofday(&cur, NULL); + if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > PCILIB_REGISTER_TIMEOUT) break; + + ipecamera_datacpy(&val, rd, bank); + } + + if ((val & READ_READY_BIT) == 0) { + pcilib_error("Timeout writting register value"); + return PCILIB_ERROR_TIMEOUT; + } + + if (val & READ_ERROR_BIT) { + pcilib_error("Error writting register value"); + return PCILIB_ERROR_FAILED; + } + + 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); + goto retry; + } + pcilib_error("Address verification failed during register write"); + return PCILIB_ERROR_VERIFY; + } + + if ((val&ipecamera_bit_mask[bits]) != value) { + pcilib_error("Value verification failed during register read (%lu != %lu)", val&ipecamera_bit_mask[bits], value); + return PCILIB_ERROR_VERIFY; + } + //printf("%i\n", val&ipecamera_bit_mask[bits]); + return 0; +} |