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
6481a514
Commit
6481a514
authored
Oct 06, 2016
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Save and restore write pointer reported by driver
parent
e5342921
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
153 additions
and
11 deletions
+153
-11
camogm.c
src/camogm.c
+12
-3
camogm.h
src/camogm.h
+1
-0
camogm_jpeg.c
src/camogm_jpeg.c
+140
-8
No files found.
src/camogm.c
View file @
6481a514
...
@@ -1872,9 +1872,9 @@ int main(int argc, char *argv[])
...
@@ -1872,9 +1872,9 @@ int main(int argc, char *argv[])
const
char
usage
[]
=
"This program allows recording of the video/images acquired by Elphel camera to the storage media.
\n
"
\
const
char
usage
[]
=
"This program allows recording of the video/images acquired by Elphel camera to the storage media.
\n
"
\
"It is designed to run in the background and accept commands through a named pipe or a socket.
\n\n
"
\
"It is designed to run in the background and accept commands through a named pipe or a socket.
\n\n
"
\
"Usage:
\n\n
"
\
"Usage:
\n\n
"
\
"%s -n <named_pipe_name> -p <port_number>
\n\n
"
\
"%s -n <named_pipe_name> -p <port_number>
[-s state_file_name]
\n\n
"
\
"i.e.:
\n\n
"
\
"i.e.:
\n\n
"
\
"%s -n /var/state/camogm_cmd -p 1234
\n\n
"
\
"%s -n /var/state/camogm_cmd -p 1234
-s /mnt/sda1/write_pos
\n\n
"
\
"When the program is running you may send commands by writing strings to the command file
\n
"
\
"When the program is running you may send commands by writing strings to the command file
\n
"
\
"(/var/state/camogm_cmd in the example above) or to the socket. The complete list of available commands is available
\n
"
\
"(/var/state/camogm_cmd in the example above) or to the socket. The complete list of available commands is available
\n
"
\
"on Elphel Wiki (http://wiki.elphel.com/index.php?title=Camogm), here is the example of usage
\n
"
\
"on Elphel Wiki (http://wiki.elphel.com/index.php?title=Camogm), here is the example of usage
\n
"
\
...
@@ -1890,13 +1890,15 @@ int main(int argc, char *argv[])
...
@@ -1890,13 +1890,15 @@ int main(int argc, char *argv[])
int
ret
;
int
ret
;
int
opt
;
int
opt
;
uint16_t
port_num
=
0
;
uint16_t
port_num
=
0
;
size_t
str_len
;
char
pipe_name_str
[
ELPHEL_PATH_MAX
]
=
{
0
};
char
pipe_name_str
[
ELPHEL_PATH_MAX
]
=
{
0
};
char
state_name_str
[
ELPHEL_PATH_MAX
]
=
{
0
};
if
((
argc
<
5
)
||
(
argv
[
1
][
1
]
==
'-'
))
{
if
((
argc
<
5
)
||
(
argv
[
1
][
1
]
==
'-'
))
{
printf
(
usage
,
argv
[
0
],
argv
[
0
]);
printf
(
usage
,
argv
[
0
],
argv
[
0
]);
return
EXIT_SUCCESS
;
return
EXIT_SUCCESS
;
}
}
while
((
opt
=
getopt
(
argc
,
argv
,
"n:p:h"
))
!=
-
1
)
{
while
((
opt
=
getopt
(
argc
,
argv
,
"n:p:
s:
h"
))
!=
-
1
)
{
switch
(
opt
)
{
switch
(
opt
)
{
case
'n'
:
case
'n'
:
strncpy
(
pipe_name_str
,
(
const
char
*
)
optarg
,
ELPHEL_PATH_MAX
-
1
);
strncpy
(
pipe_name_str
,
(
const
char
*
)
optarg
,
ELPHEL_PATH_MAX
-
1
);
...
@@ -1907,6 +1909,9 @@ int main(int argc, char *argv[])
...
@@ -1907,6 +1909,9 @@ int main(int argc, char *argv[])
case
'h'
:
case
'h'
:
printf
(
usage
,
argv
[
0
],
argv
[
0
]);
printf
(
usage
,
argv
[
0
],
argv
[
0
]);
return
EXIT_SUCCESS
;
return
EXIT_SUCCESS
;
case
's'
:
strncpy
(
state_name_str
,
(
const
char
*
)
optarg
,
ELPHEL_PATH_MAX
-
1
);
break
;
}
}
}
}
...
@@ -1926,6 +1931,10 @@ int main(int argc, char *argv[])
...
@@ -1926,6 +1931,10 @@ int main(int argc, char *argv[])
return
EXIT_FAILURE
;
return
EXIT_FAILURE
;
}
}
sstate
.
rawdev
.
thread_state
=
STATE_RUNNING
;
sstate
.
rawdev
.
thread_state
=
STATE_RUNNING
;
str_len
=
strlen
(
state_name_str
);
if
(
str_len
>
0
)
{
strncpy
(
&
sstate
.
rawdev
.
state_path
,
state_name_str
,
str_len
+
1
);
}
ret
=
listener_loop
(
&
sstate
);
ret
=
listener_loop
(
&
sstate
);
...
...
src/camogm.h
View file @
6481a514
...
@@ -128,6 +128,7 @@ typedef struct {
...
@@ -128,6 +128,7 @@ typedef struct {
volatile
int
thread_state
;
volatile
int
thread_state
;
unsigned
char
*
disk_mmap
;
unsigned
char
*
disk_mmap
;
int
sysfs_fd
;
int
sysfs_fd
;
char
state_path
[
ELPHEL_PATH_MAX
];
}
rawdev_buffer
;
}
rawdev_buffer
;
/**
/**
...
...
src/camogm_jpeg.c
View file @
6481a514
...
@@ -31,6 +31,134 @@
...
@@ -31,6 +31,134 @@
#include <elphel/ahci_cmd.h>
#include <elphel/ahci_cmd.h>
#include "camogm_jpeg.h"
#include "camogm_jpeg.h"
#include "camogm_read.h"
/** State file record format. It includes device path in /dev, starting, current and ending LBAs */
#define STATE_FILE_FORMAT "%s\t%llu\t%llu\t%llu\n"
/** Get starting and endign LBAs of the partition specified as raw device buffer */
static
int
get_disk_range
(
struct
range
*
range
)
{
FILE
*
f
;
// get raw device buffer starting postion on disk
f
=
fopen
(
SYSFS_AHCI_LBA_START
,
"r"
);
if
(
f
==
NULL
)
{
return
-
1
;
}
fscanf
(
f
,
"%llu
\n
"
,
&
range
->
from
);
fclose
(
f
);
// get raw device buffer ending postion on disk
f
=
fopen
(
SYSFS_AHCI_LBA_END
,
"r"
);
if
(
f
==
NULL
)
{
return
-
1
;
}
fscanf
(
f
,
"%llu
\n
"
,
&
range
->
to
);
fclose
(
f
);
return
0
;
}
/** Get write pointer from a file. This functions check not only the name of a partition, but
* its geometry as well */
static
int
find_state
(
FILE
*
f
,
uint64_t
*
pos
,
const
rawdev_buffer
*
rawdev
)
{
size_t
len
;
uint64_t
start_pos
,
curr_pos
,
end_pos
;
struct
range
range
;
char
buff
[
ELPHEL_PATH_MAX
];
char
dev_name
[
ELPHEL_PATH_MAX
];
if
(
f
==
NULL
||
pos
==
NULL
)
return
-
1
;
if
(
get_disk_range
(
&
range
)
!=
0
)
{
return
-
1
;
}
// skip first line containing file header
fgets
(
buff
,
ELPHEL_PATH_MAX
,
f
);
while
(
fgets
(
buff
,
ELPHEL_PATH_MAX
,
f
)
!=
NULL
)
{
sscanf
(
buff
,
STATE_FILE_FORMAT
,
dev_name
,
&
start_pos
,
&
curr_pos
,
&
end_pos
);
len
=
strlen
(
dev_name
);
if
(
strncmp
(
rawdev
->
rawdev_path
,
dev_name
,
len
)
==
0
&&
range
.
from
==
start_pos
&&
range
.
to
==
end_pos
)
{
*
pos
=
curr_pos
;
break
;
}
}
return
0
;
}
/** Read state from file and restore disk write pointer */
static
int
open_state_file
(
const
rawdev_buffer
*
rawdev
)
{
int
fd
,
len
;
FILE
*
f
;
int
ret
=
0
;
uint64_t
curr_pos
;
char
buff
[
SMALL_BUFF_LEN
]
=
{
0
};
if
(
strlen
(
rawdev
->
state_path
)
==
0
)
{
return
ret
;
}
f
=
fopen
(
rawdev
->
state_path
,
"r"
);
if
(
f
!=
NULL
)
{
if
(
find_state
(
f
,
&
curr_pos
,
rawdev
)
!=
-
1
)
{
fd
=
open
(
SYSFS_AHCI_LBA_CURRENT
,
O_WRONLY
);
if
(
fd
>=
0
)
{
len
=
snprintf
(
buff
,
SMALL_BUFF_LEN
,
"%llu"
,
curr_pos
);
write
(
fd
,
buff
,
len
+
1
);
close
(
fd
);
}
else
{
ret
=
-
1
;
}
}
fclose
(
f
);
}
else
{
ret
=
-
1
;
}
return
ret
;
}
/** Save current position of the disk write pointer */
static
int
save_state_file
(
const
rawdev_buffer
*
rawdev
)
{
int
ret
=
0
;
FILE
*
f
;
struct
range
range
;
uint64_t
curr_pos
;
if
(
strlen
(
rawdev
->
state_path
)
==
0
)
{
return
ret
;
}
if
(
get_disk_range
(
&
range
)
!=
0
)
{
return
-
1
;
}
// get raw device buffer current postion on disk, this position indicates where recording has stopped
f
=
fopen
(
SYSFS_AHCI_LBA_CURRENT
,
"r"
);
if
(
f
==
NULL
)
{
return
-
1
;
}
fscanf
(
f
,
"%llu
\n
"
,
&
curr_pos
);
fclose
(
f
);
// save pointers to a regular file
f
=
fopen
(
rawdev
->
state_path
,
"w"
);
if
(
f
==
NULL
)
{
return
-
1
;
}
fprintf
(
f
,
"Device
\t\t
Start LBA
\t
Current LBA
\t
End LBA
\n
"
);
fprintf
(
f
,
STATE_FILE_FORMAT
,
rawdev
->
rawdev_path
,
range
.
from
,
curr_pos
,
range
.
to
);
fclose
(
f
);
return
ret
;
}
int
camogm_init_jpeg
(
camogm_state
*
state
)
int
camogm_init_jpeg
(
camogm_state
*
state
)
{
{
...
@@ -82,15 +210,17 @@ int camogm_start_jpeg(camogm_state *state)
...
@@ -82,15 +210,17 @@ int camogm_start_jpeg(camogm_state *state)
}
}
}
}
}
else
{
}
else
{
if
(
state
->
rawdev_op
)
{
if
(
open_state_file
(
&
state
->
rawdev
)
!=
0
)
{
D0
(
fprintf
(
debug_file
,
"Could not set write pointer via sysfs, recording will start from the beginning of partition: "
"%s
\n
"
,
state
->
rawdev
.
rawdev_path
));
}
state
->
rawdev
.
sysfs_fd
=
open
(
SYSFS_AHCI_WRITE
,
O_WRONLY
);
state
->
rawdev
.
sysfs_fd
=
open
(
SYSFS_AHCI_WRITE
,
O_WRONLY
);
fprintf
(
debug_file
,
"Open sysfs file: %s
\n
"
,
SYSFS_AHCI_WRITE
);
D6
(
fprintf
(
debug_file
,
"Open sysfs file: %s
\n
"
,
SYSFS_AHCI_WRITE
)
);
if
(
state
->
rawdev
.
sysfs_fd
<
0
)
{
if
(
state
->
rawdev
.
sysfs_fd
<
0
)
{
D0
(
fprintf
(
debug_file
,
"Error opening sysfs file: %s
\n
"
,
SYSFS_AHCI_WRITE
));
D0
(
fprintf
(
debug_file
,
"Error opening sysfs file: %s
\n
"
,
SYSFS_AHCI_WRITE
));
return
-
CAMOGM_FRAME_FILE_ERR
;
return
-
CAMOGM_FRAME_FILE_ERR
;
}
}
}
}
}
return
0
;
return
0
;
}
}
...
@@ -171,10 +301,12 @@ int camogm_end_jpeg(camogm_state *state)
...
@@ -171,10 +301,12 @@ int camogm_end_jpeg(camogm_state *state)
if
(
write
(
state
->
rawdev
.
sysfs_fd
,
&
fdata
,
sizeof
(
struct
frame_data
))
<
0
)
{
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
,
"Error sending 'finish' command to driver
\n
"
));
}
}
D
0
(
fprintf
(
debug_file
,
"Closing sysfs file %s
\n
"
,
SYSFS_AHCI_WRITE
));
D
6
(
fprintf
(
debug_file
,
"Closing sysfs file %s
\n
"
,
SYSFS_AHCI_WRITE
));
ret
=
close
(
state
->
rawdev
.
sysfs_fd
);
ret
=
close
(
state
->
rawdev
.
sysfs_fd
);
if
(
ret
==
-
1
)
if
(
ret
==
-
1
)
D0
(
fprintf
(
debug_file
,
"Error: %s
\n
"
,
strerror
(
errno
)));
D0
(
fprintf
(
debug_file
,
"Error: %s
\n
"
,
strerror
(
errno
)));
save_state_file
(
&
state
->
rawdev
);
}
}
return
ret
;
return
ret
;
}
}
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