Commit d336db3a authored by Mikhail Karpenko's avatar Mikhail Karpenko

Write driver commands to sysfs

parent 9a60ffa3
......@@ -490,9 +490,6 @@ int sendImageFrame(camogm_state *state)
int * ifp_this = (int*)&(state->this_frame_params[state->port_num]);
int fp;
int port = state->port_num;
unsigned char app15[64] = {0xff, 0xef};
int app15_pos = 0;
int stuffing;
// This is probably needed only for Quicktime (not to exceed already allocated frame index)
if (state->frameno >= (state->max_frames)) {
......@@ -606,28 +603,15 @@ int sendImageFrame(camogm_state *state)
state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port];
state->packetchunks[state->chunk_index ].bytes = state->exifSize[port];
state->packetchunks[state->chunk_index++].chunk = state->ed[port];
app15_pos = state->chunk_index++;
state->packetchunks[state->chunk_index ].bytes = state->head_size[port] - 2;
state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[port][2]);
stuffing = 32 - (2 + state->exifSize[port] + state->head_size[port]) % 32;
} else {
D3(fprintf(debug_file, "_8_"));
app15_pos = state->chunk_index++;
state->packetchunks[state->chunk_index ].bytes = state->head_size[port];
state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port];
stuffing = 32 - (state->head_size[port] % 32);
}
D3(fprintf(debug_file, "_9_"));
// align JPEG (+ Exif) header to 32 bytes by adding APP15 marker
if (stuffing < 4) {
stuffing += 32;
}
app15[3] = stuffing - 2;
state->packetchunks[app15_pos].bytes = stuffing;
state->packetchunks[app15_pos].chunk = app15;
fprintf(debug_file, "\nadd %d stuffing bytes as APP15\n", stuffing);
/* JPEG image data may be split in two segments (rolled over buffer end) - process both variants */
if ((state->cirbuf_rp[port] + state->jpeg_len) > state->circ_buff_size[port]) { // two segments
/* copy from the beginning of the frame to the end of the buffer */
......
......@@ -124,6 +124,7 @@ typedef struct {
pthread_t tid;
volatile int thread_state;
unsigned char *disk_mmap;
int sysfs_fd;
} rawdev_buffer;
/**
......
......@@ -31,10 +31,21 @@
#include "camogm_jpeg.h"
/** The position of size field in copy buffer */
#define VECTOR_SZ_POS 0
/** The position of vector pointer field in copy buffer */
#define POINTER_POS 1
/* this should be in system includes */
#define DRV_CMD_WRITE (1 << 0)
#define DRV_CMD_FINISH (1 << 1)
#define DRV_CMD_EXIF (1 << 2)
struct frame_data {
unsigned int sensor_port;
int cirbuf_ptr;
int jpeg_len;
int meta_index;
int cmd;
};
const char sysfs_fname[] = "/sys/devices/soc0/amba@0/80000000.elphel-ahci/write";
/* end of system includes */
int camogm_init_jpeg(camogm_state *state)
{
......@@ -84,12 +95,15 @@ int camogm_start_jpeg(camogm_state *state)
D3(fprintf(debug_file, "Open raw device %s; start_pos = %llu, end_pos = %llu, curr_pos = %llu\n", state->rawdev.rawdev_path,
state->rawdev.start_pos, state->rawdev.end_pos, state->rawdev.curr_pos_w));
lseek64(state->rawdev.rawdev_fd, state->rawdev.curr_pos_w, SEEK_SET);
state->rawdev.sysfs_fd = open(sysfs_fname, O_WRONLY);
if (state->rawdev.sysfs_fd < 0) {
D0(fprintf(debug_file, "Error opening sysfs file: %s\n", sysfs_fname));
return -CAMOGM_FRAME_FILE_ERR;
}
}
}
fprintf(debug_file, "Start recording buffer usage statistics\n");
fprintf(debug_file, "\"JPEG write time, us\",\"free buff, %\",\"free buff, %\",\"free buff, %\",\"free buff, %\"\n");
return 0;
}
......@@ -111,8 +125,8 @@ int camogm_frame_jpeg(camogm_state *state)
int port = state->port_num;
uint32_t start_time, end_time;
off_t free_space;
struct frame_data fdata = {0};
start_time = lseek(state->fd_circ[0], LSEEK_CIRC_UTIME, SEEK_END);
if (!state->rawdev_op) {
l = 0;
for (i = 0; i < (state->chunk_index) - 1; i++) {
......@@ -134,104 +148,23 @@ int camogm_frame_jpeg(camogm_state *state)
}
close(state->ivf);
} else {
// D3(fprintf(debug_file, "\n%s: current pointers start_pos = %llu, end_pos = %llu, curr_pos = %llu, data in buffer %d\n", __func__,
// state->rawdev.start_pos, state->rawdev.end_pos, state->rawdev.curr_pos_w, l));
// split_index = -1;
// for (int i = 0, total_len = 0; i < state->chunk_index - 1; i++) {
// total_len += state->packetchunks[i + 1].bytes;
// if (total_len + state->rawdev.curr_pos_w > state->rawdev.end_pos) {
// split_index = i;
// chunks_used++;
// D3(fprintf(debug_file, "\n>>> raw storage roll over detected\n"));
// break;
// }
// }
// k = 0;
// l = 0;
// for (int i = 0; i < chunks_used; i++) {
// ++k;
// if (i == split_index) {
// // one of the chunks rolls over the end of the raw storage, split it into two segments and
// // use additional chunk in chunks_iovec for this additional segment
// split_cntr = state->rawdev.end_pos - (l + state->rawdev.curr_pos_w);
// split_ptr = state->packetchunks[k].chunk + split_cntr;
//
// D3(fprintf(debug_file, "Splitting chunk #%d: total chunk size = %ld, start address = 0x%p\n",
// i, state->packetchunks[k].bytes, state->packetchunks[k].chunk));
//
// // be careful with indexes here
// chunks_iovec[i].iov_base = state->packetchunks[k].chunk;
// chunks_iovec[i].iov_len = split_cntr;
// l += chunks_iovec[i].iov_len;
// chunks_iovec[++i].iov_base = split_ptr + 1;
// chunks_iovec[i].iov_len = state->packetchunks[k].bytes - split_cntr;
// l += chunks_iovec[i].iov_len;
// } else {
// chunks_iovec[i].iov_base = state->packetchunks[k].chunk;
// chunks_iovec[i].iov_len = state->packetchunks[k].bytes;
// l += chunks_iovec[i].iov_len;
// }
// }
//
// if (split_index < 0) {
// iovlen = writev(state->rawdev.rawdev_fd, chunks_iovec, chunks_used);
// } else {
// iovlen = writev(state->rawdev.rawdev_fd, chunks_iovec, split_index + 1);
// fprintf(debug_file, "write first part: split_index = %d, %d bytes written\n", split_index, iovlen);
// if (lseek64(state->rawdev.rawdev_fd, state->rawdev.start_pos, SEEK_SET) != state->rawdev.start_pos) {
// perror(__func__);
// D0(fprintf(debug_file, "error positioning file pointer to the beginning of raw device\n"));
// return -CAMOGM_FRAME_FILE_ERR;
// }
// state->rawdev.overrun++;
// iovlen += writev(state->rawdev.rawdev_fd, &chunks_iovec[split_index + 1], chunks_used - split_index);
// fprintf(debug_file, "write second part: split_index + 1 = %d, chunks_used - split_index = %d, %d bytes written in total\n",
// split_index + 1, chunks_used - split_index, iovlen);
// }
// if (iovlen < l) {
// j = errno;
// perror(__func__);
// D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
// return -CAMOGM_FRAME_FILE_ERR;
// }
// state->rawdev.curr_pos_w += l;
// if (state->rawdev.curr_pos_w > state->rawdev.end_pos)
// state->rawdev.curr_pos_w = state->rawdev.curr_pos_w - state->rawdev.end_pos + state->rawdev.start_pos;
// D6(fprintf(debug_file, "%d bytes written, curr_pos = %llu\n", l, state->rawdev.curr_pos_w));
uint8_t buff[128] = {0};
uint32_t *buff_p = (uint32_t *)buff;
uint8_t *pos;
int fd = open("/sys/devices/soc0/amba@0/80000000.elphel-ahci/write", O_WRONLY);
if (fd < 0) {
perror("ERROR: can not open test_write file\n");
return -CAMOGM_FRAME_FILE_ERR;
}
buff_p[VECTOR_SZ_POS] = state->chunk_index - 1;
fprintf(debug_file, "dump iovect array\n");
for (int i = 0; i < state->chunk_index - 1; i++) {
fprintf(debug_file, "ptr: %p, length: %ld\n", state->packetchunks[i + 1].chunk, state->packetchunks[i + 1].bytes);
}
buff_p[POINTER_POS] = (uint32_t) &state->packetchunks[1];
if (write(fd, buff, 8) < 0) {
perror("Can not pass IO vector to driver:");
fdata.sensor_port = port;
fdata.cirbuf_ptr = state->cirbuf_rp[port];
fdata.jpeg_len = state->jpeg_len;
if (state->exif) {
fdata.meta_index = state->this_frame_params[port].meta_index;
fdata.cmd |= DRV_CMD_EXIF;
}
fdata.cmd |= DRV_CMD_WRITE;
if (write(state->rawdev.sysfs_fd, &fdata, sizeof(struct frame_data)) < 0) {
D0(fprintf(debug_file, "Can not pass IO vector to driver: %s\n", strerror(errno)));
return -CAMOGM_FRAME_FILE_ERR;
}
close(fd);
}
end_time = lseek(state->fd_circ[0], LSEEK_CIRC_UTIME, SEEK_END);
// fprintf(debug_file, "JPEG write time = %u us\n", end_time - start_time);
// fprintf(debug_file, "Free space in buffers: ");
// for (int i = 0; i < SENSOR_PORTS; i++) {
// int buff_size, jpeg_pos;
// jpeg_pos = lseek(state->fd_circ[i], 0 , SEEK_CUR);
// free_space = lseek(state->fd_circ[i], LSEEK_CIRC_FREE, SEEK_END);
// buff_size = lseek(state->fd_circ[i], 0, SEEK_END);
// lseek(state->fd_circ[i], jpeg_pos, SEEK_SET);
// fprintf(debug_file, "chn %d = %ld ",
// i,
// (int)(100 * (float)free_space / (float)buff_size));
// }
// fprintf(debug_file, "\b\n");
return 0;
}
......@@ -246,9 +179,22 @@ int camogm_frame_jpeg(camogm_state *state)
int camogm_end_jpeg(camogm_state *state)
{
int ret = 0;
struct frame_data fdata = {0};
if (state->rawdev_op) {
ret = close(state->rawdev.rawdev_fd);
D0(fprintf(debug_file, "Closing raw device %s\n", state->rawdev.rawdev_path));
ret = close(state->rawdev.rawdev_fd);
if (ret == -1)
D0(fprintf(debug_file, "Error: %s\n", strerror(errno)));
fdata.cmd = DRV_CMD_FINISH;
if (write(state->rawdev.sysfs_fd, &fdata, sizeof(struct frame_data)) < 0) {
D0(fprintf(debug_file, "Error sending 'finish' command to driver\n"));
}
D0(fprintf(debug_file, "Closing sysfs file %s\n", sysfs_fname));
ret = close(state->rawdev.sysfs_fd);
if (ret == -1)
D0(fprintf(debug_file, "Error: %s\n", strerror(errno)));
}
return ret;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment