Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
elphel-apps-camogm
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
elphel-apps-camogm
Commits
d589ff4f
Commit
d589ff4f
authored
Sep 14, 2016
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch with AHCI driver control
parents
7b8b1871
40500893
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
211 additions
and
81 deletions
+211
-81
Makefile
Makefile
+2
-2
camogm.c
camogm.c
+174
-3
camogm.h
camogm.h
+2
-1
camogm_jpeg.c
camogm_jpeg.c
+30
-73
camogm_read.c
camogm_read.c
+0
-2
camogm_read.h
camogm_read.h
+3
-0
No files found.
Makefile
View file @
d589ff4f
...
...
@@ -3,9 +3,9 @@ PHPFILES = camogmstate.php
CONFIGS
=
qt_source
SRCS
=
camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c
OBJS
=
camogm.o camogm_ogm.o camogm_jpeg.o camogm_mov.o camogm_kml.o camogm_read.o index_list.o
OBJS
=
$
(
SRCS:.c
=
.o
)
CFLAGS
+=
-Wall
-I
$(STAGING_KERNEL_DIR)
/include/elphel
CFLAGS
+=
-Wall
-I
$(STAGING_KERNEL_DIR)
/include/elphel
-I
$(STAGING_DIR_HOST)
/usr/include-uapi
LDLIBS
+=
-logg
-pthread
-lm
SYSCONFDIR
=
/etc/
...
...
camogm.c
View file @
d589ff4f
...
...
@@ -27,6 +27,8 @@
#include <sys/stat.h>
#include <string.h>
#include <getopt.h>
#include <ctype.h>
#include <elphel/ahci_cmd.h>
#include "camogm_ogm.h"
#include "camogm_jpeg.h"
...
...
@@ -101,6 +103,11 @@ typedef enum {
FILE_PATH
}
path_type
;
enum
sysfs_path_type
{
TYPE_START
,
TYPE_SIZE
};
int
debug_level
;
FILE
*
debug_file
;
...
...
@@ -139,7 +146,10 @@ void camogm_set_start_after_timestamp(camogm_state *state, double d);
void
camogm_set_max_frames
(
camogm_state
*
state
,
int
d
);
void
camogm_set_frames_per_chunk
(
camogm_state
*
state
,
int
d
);
uint64_t
get_disk_size
(
const
char
*
name
);
static
uint64_t
get_disk_size
(
const
char
*
name
);
static
int
get_sysfs_name
(
const
char
*
dev_name
,
char
*
sys_name
,
size_t
str_sz
,
int
type
);
static
int
get_disk_range
(
const
char
*
name
,
struct
range
*
rng
);
static
int
set_disk_range
(
const
struct
range
*
rng
);
int
open_files
(
camogm_state
*
state
);
unsigned
long
getGPValue
(
unsigned
int
port
,
unsigned
long
GPNumber
);
void
setGValue
(
unsigned
int
port
,
unsigned
long
GNumber
,
unsigned
long
value
);
...
...
@@ -571,7 +581,7 @@ int sendImageFrame(camogm_state *state)
D3
(
fprintf
(
debug_file
,
"_5_"
));
// update the Exif header with the current frame metadata
state
->
exifSize
[
port
]
=
lseek
(
state
->
fd_exif
[
port
],
1
,
SEEK_END
);
// at the beginning of page 1 - position == page length
if
(
state
->
exifSize
>
0
)
{
if
(
state
->
exifSize
[
port
]
>
0
)
{
//state->this_frame_params.meta_index
lseek
(
state
->
fd_exif
[
port
],
state
->
this_frame_params
[
port
].
meta_index
,
SEEK_END
);
// select meta page to use (matching frame)
rslt
=
read
(
state
->
fd_exif
[
port
],
state
->
ed
[
port
],
state
->
exifSize
[
port
]);
...
...
@@ -815,6 +825,18 @@ void camogm_set_prefix(camogm_state *state, const char * p, path_type type)
D0
(
fprintf
(
debug_file
,
"WARNING: raw device write initiated
\n
"
));
state
->
rawdev_op
=
1
;
}
/* debug code follows*/
struct
range
rng
=
{
.
from
=
0
,
.
to
=
0
};
if
(
get_disk_range
(
state
->
rawdev
.
rawdev_path
,
&
rng
)
==
0
)
{
set_disk_range
(
&
rng
);
}
else
{
D0
(
fprintf
(
debug_file
,
"ERROR: unable to get disk size and starting sector
\n
"
));
}
/* end of debug code */
}
}
...
...
@@ -1521,7 +1543,7 @@ int listener_loop(camogm_state *state)
* @param name pointer to disk name string
* @return disk size in bytes if it was read correctly and 0 otherwise
*/
uint64_t
get_disk_size
(
const
char
*
name
)
static
uint64_t
get_disk_size
(
const
char
*
name
)
{
int
fd
;
uint64_t
dev_sz
;
...
...
@@ -1539,6 +1561,154 @@ uint64_t get_disk_size(const char *name)
return
dev_sz
;
}
/**
* @brief Make sysfs path from disk name in accordance with the type provided.
* The 'start' file does not exist for full disk path (/dev/sda) and this function
* returns empty string in @e sys_name and non-zero return value.
* @param[in] dev_name pointer to a string containing device name
* @param[out] sys_name pointer to a string where sysfs path will be stored
* @param[in] str_sz the size of @e dname and @e sname strings including the
* terminating null byte
* @param[in] type the type of sysfs path required. Can be one of #sysfs_path_type
* @return The number of characters in resulting path, including the terminating
* null byte, or a negative value in case of an error.
*/
static
int
get_sysfs_name
(
const
char
*
dev_name
,
char
*
sys_name
,
size_t
str_sz
,
int
type
)
{
int
ret
=
-
1
;
const
char
prefix
[]
=
"/sys/block/"
;
char
size_name
[]
=
"size"
;
char
start_name
[]
=
"start"
;
char
device_name
[
ELPHEL_PATH_MAX
]
=
{
0
};
char
disk_name
[
ELPHEL_PATH_MAX
]
=
{
0
};
char
part_name
[
ELPHEL_PATH_MAX
]
=
{
0
};
char
*
postfix
=
NULL
;
char
*
ptr
=
NULL
;
size_t
dname_sz
=
strlen
(
dev_name
)
-
1
;
strncpy
(
device_name
,
dev_name
,
ELPHEL_PATH_MAX
);
// strip trailing slash
if
(
device_name
[
dname_sz
]
==
'/'
)
{
device_name
[
dname_sz
]
=
'\0'
;
dname_sz
--
;
}
// get partition and disk names
ptr
=
strrchr
(
device_name
,
'/'
);
if
(
ptr
==
NULL
)
{
D0
(
fprintf
(
debug_file
,
"%s: the path specified is invalid
\n
"
,
__func__
));
return
ret
;
}
strcpy
(
part_name
,
ptr
+
1
);
strcpy
(
disk_name
,
ptr
+
1
);
if
(
strlen
(
disk_name
)
>
0
)
disk_name
[
strlen
(
disk_name
)
-
1
]
=
'\0'
;
if
(
type
==
TYPE_SIZE
)
postfix
=
size_name
;
else
if
(
type
==
TYPE_START
)
postfix
=
start_name
;
if
(
isdigit
(
device_name
[
dname_sz
]))
{
// we've got partition
ret
=
snprintf
(
sys_name
,
str_sz
,
"%s%s/%s/%s"
,
prefix
,
disk_name
,
part_name
,
postfix
);
}
else
{
// we've got entire disk
ret
=
snprintf
(
sys_name
,
str_sz
,
"%s%s/%s"
,
prefix
,
part_name
,
postfix
);
if
(
type
==
TYPE_START
)
// the 'start' does not exist for full disk, notify caller
// that we've got this situation here
sys_name
[
0
]
=
'\0'
;
}
return
ret
;
}
/**
* @brief Get disk start and end sectors. If the name specified is the name of a disk instead of
* the name of a partition on that disk (i.e /dev/sda instead /dev/sda2), then the full size of the
* disk is returned. This function is used with #set_disk_range to allocate raw device buffer on a disk.
* @param[in] name pointer to disk name string
* @param[out] rng pointer to the structure containing disk size
* @return 0 if disk size was retrieved successfully and -1 in case of an error
*/
static
int
get_disk_range
(
const
char
*
name
,
struct
range
*
rng
)
{
int
ret
=
0
;
int
fd
;
uint64_t
val
;
char
data
[
SMALL_BUFF_LEN
]
=
{
0
};
char
sysfs_name
[
ELPHEL_PATH_MAX
]
=
{
0
};
// read start LBA
if
(
get_sysfs_name
(
name
,
sysfs_name
,
ELPHEL_PATH_MAX
,
TYPE_START
)
>
0
)
{
if
(
strlen
(
sysfs_name
)
>
0
)
{
fd
=
open
(
sysfs_name
,
O_RDONLY
);
if
(
fd
>=
0
)
{
read
(
fd
,
data
,
SMALL_BUFF_LEN
);
if
((
val
=
strtoull
(
data
,
NULL
,
10
))
!=
0
)
rng
->
from
=
val
;
else
ret
=
-
1
;
close
(
fd
);
}
}
else
{
rng
->
from
=
0
;
}
}
// read disk size in LBA
if
(
get_sysfs_name
(
name
,
sysfs_name
,
ELPHEL_PATH_MAX
,
TYPE_SIZE
)
>
0
)
{
fd
=
open
(
sysfs_name
,
O_RDONLY
);
if
(
fd
>=
0
)
{
read
(
fd
,
data
,
SMALL_BUFF_LEN
);
if
((
val
=
strtoull
(
data
,
NULL
,
10
))
!=
0
)
rng
->
to
=
rng
->
from
+
val
;
else
ret
=
-
1
;
close
(
fd
);
}
}
// sanity check
if
(
rng
->
from
>=
rng
->
to
)
ret
=
-
1
;
return
ret
;
}
/**
* @brief Pass raw device buffer start and end LBAs to driver via its files in
* sysfs. This function is used with #get_disk_range to allocate raw device buffer on a disk.
* @param[in] name path to sysfs disk driver entry
* @param[in] rng pointer to structure containing disk size
* @return 0 if the values from @e rng were set successfully and -1 in case of an error
*/
static
int
set_disk_range
(
const
struct
range
*
rng
)
{
int
fd
;
int
ret
=
0
;
char
buff
[
SMALL_BUFF_LEN
]
=
{
0
};
int
len
;
fd
=
open
(
SYSFS_AHCI_LBA_START
,
O_WRONLY
);
if
(
fd
<
0
)
return
-
1
;
len
=
snprintf
(
buff
,
SMALL_BUFF_LEN
,
"%llu"
,
rng
->
from
);
write
(
fd
,
buff
,
len
+
1
);
close
(
fd
);
fd
=
open
(
SYSFS_AHCI_LBA_END
,
O_WRONLY
);
if
(
fd
<
0
)
return
-
1
;
len
=
snprintf
(
buff
,
SMALL_BUFF_LEN
,
"%llu"
,
rng
->
to
);
write
(
fd
,
buff
,
len
+
1
);
close
(
fd
);
return
ret
;
}
/**
* @brief Select a sensor channel with minimum free space left in the buffer. The channel will
* be selected from the list of active channels.
...
...
@@ -1566,6 +1736,7 @@ unsigned int select_port(camogm_state *state)
}
}
}
return
chn
;
}
...
...
camogm.h
View file @
d589ff4f
...
...
@@ -124,6 +124,7 @@ typedef struct {
pthread_t
tid
;
volatile
int
thread_state
;
unsigned
char
*
disk_mmap
;
int
sysfs_fd
;
}
rawdev_buffer
;
/**
...
...
@@ -186,7 +187,7 @@ typedef struct {
int
formats
;
///< bitmask of used (initialized) formats
int
format
;
///< output file format
int
set_format
;
///< output format to set (will be updated after stop)
elph_packet_chunk
packetchunks
[
7
];
elph_packet_chunk
packetchunks
[
8
];
int
chunk_index
;
int
buf_overruns
[
SENSOR_PORTS
];
int
buf_min
[
SENSOR_PORTS
];
...
...
camogm_jpeg.c
View file @
d589ff4f
...
...
@@ -27,6 +27,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <c313a.h>
#include <elphel/ahci_cmd.h>
#include "camogm_jpeg.h"
...
...
@@ -69,15 +71,12 @@ int camogm_start_jpeg(camogm_state *state)
}
}
else
{
if
(
state
->
rawdev_op
)
{
state
->
rawdev
.
rawdev_fd
=
open
(
state
->
rawdev
.
rawdev_path
,
O_RDWR
);
if
(
state
->
rawdev
.
rawdev_fd
<
0
)
{
D0
(
perror
(
__func__
));
D0
(
fprintf
(
debug_file
,
"Error opening
raw device %s
\n
"
,
state
->
rawdev
.
rawdev_path
));
state
->
rawdev
.
sysfs_fd
=
open
(
SYSFS_AHCI_WRITE
,
O_WRONLY
);
fprintf
(
debug_file
,
"Open sysfs file: %s
\n
"
,
SYSFS_AHCI_WRITE
);
if
(
state
->
rawdev
.
sysfs_fd
<
0
)
{
D0
(
fprintf
(
debug_file
,
"Error opening
sysfs file: %s
\n
"
,
SYSFS_AHCI_WRITE
));
return
-
CAMOGM_FRAME_FILE_ERR
;
}
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
);
}
}
...
...
@@ -93,13 +92,11 @@ int camogm_start_jpeg(camogm_state *state)
*/
int
camogm_frame_jpeg
(
camogm_state
*
state
)
{
int
i
,
j
,
k
,
split_index
;
int
chunks_used
=
state
->
chunk_index
-
1
;
int
i
,
j
;
ssize_t
iovlen
,
l
=
0
;
struct
iovec
chunks_iovec
[
8
];
unsigned
char
*
split_ptr
=
NULL
;
long
split_cntr
=
0
;
int
port
=
state
->
port_num
;
struct
frame_data
fdata
=
{
0
};
if
(
!
state
->
rawdev_op
)
{
l
=
0
;
...
...
@@ -122,70 +119,22 @@ int camogm_frame_jpeg(camogm_state *state)
}
close
(
state
->
ivf
);
}
else
{
D0
(
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
++
;
D0
(
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
));
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
);
}
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
;
}
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
;
D0
(
fprintf
(
debug_file
,
"%d bytes written, curr_pos = %llu
\n
"
,
l
,
state
->
rawdev
.
curr_pos_w
));
}
return
0
;
...
...
@@ -201,9 +150,17 @@ 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
));
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_AHCI_WRITE
));
ret
=
close
(
state
->
rawdev
.
sysfs_fd
);
if
(
ret
==
-
1
)
D0
(
fprintf
(
debug_file
,
"Error: %s
\n
"
,
strerror
(
errno
)));
}
return
ret
;
}
camogm_read.c
View file @
d589ff4f
...
...
@@ -61,8 +61,6 @@
#define CMD_DELIMITER "/?"
/** @brief The length of a buffer for command string */
#define CMD_BUFF_LEN 1024
/** @brief The length of a buffer for string formatting */
#define SMALL_BUFF_LEN 32
/** @brief 64 bit mask to align offsets to 4 kb page boundary */
#define PAGE_BOUNDARY_MASK 0xffffffffffffe000
/** @brief The size of read buffer in bytes. The data will be read from disk in blocks of this size */
...
...
camogm_read.h
View file @
d589ff4f
...
...
@@ -19,6 +19,9 @@
#include "camogm.h"
/** @brief The length of a buffer for string formatting */
#define SMALL_BUFF_LEN 32
/**
* @struct range
* @brief Container for offsets in raw device buffer
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment