Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
3c83efbe
Commit
3c83efbe
authored
Mar 05, 2011
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
DVB: separate CA management
parent
cc4cb782
Changes
7
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
580 additions
and
626 deletions
+580
-626
modules/access/dvb/Modules.am
modules/access/dvb/Modules.am
+2
-3
modules/access/dvb/access.c
modules/access/dvb/access.c
+1
-5
modules/access/dvb/dvb.h
modules/access/dvb/dvb.h
+4
-111
modules/access/dvb/en50221.c
modules/access/dvb/en50221.c
+373
-446
modules/access/dvb/en50221.h
modules/access/dvb/en50221.h
+143
-0
modules/access/dvb/http.c
modules/access/dvb/http.c
+1
-1
modules/access/dvb/linux_dvb.c
modules/access/dvb/linux_dvb.c
+56
-60
No files found.
modules/access/dvb/Modules.am
View file @
3c83efbe
SOURCES_dvb = \
access.c \
scan.c \
scan.h \
scan.c scan.h \
linux_dvb.c \
en50221.c \
en50221.c
en50221.h
\
http.c \
dvb.h \
$(NULL)
modules/access/dvb/access.c
View file @
3c83efbe
...
...
@@ -473,11 +473,7 @@ static block_t *Block( access_t *p_access )
return
NULL
;
}
if
(
p_sys
->
i_ca_handle
&&
mdate
()
>
p_sys
->
i_ca_next_event
)
{
CAMPoll
(
p_access
);
p_sys
->
i_ca_next_event
=
mdate
()
+
p_sys
->
i_ca_timeout
;
}
if
(
ufds
[
1
].
revents
)
{
...
...
modules/access/dvb/dvb.h
View file @
3c83efbe
...
...
@@ -51,113 +51,19 @@ typedef struct
typedef
struct
scan_parameter_t
scan_parameter_t
;
typedef
struct
scan_t
scan_t
;
typedef
struct
en50221_session_t
{
int
i_slot
;
int
i_resource_id
;
void
(
*
pf_handle
)(
access_t
*
,
int
,
uint8_t
*
,
int
);
void
(
*
pf_close
)(
access_t
*
,
int
);
void
(
*
pf_manage
)(
access_t
*
,
int
);
void
*
p_sys
;
}
en50221_session_t
;
#define EN50221_MMI_NONE 0
#define EN50221_MMI_ENQ 1
#define EN50221_MMI_ANSW 2
#define EN50221_MMI_MENU 3
#define EN50221_MMI_MENU_ANSW 4
#define EN50221_MMI_LIST 5
typedef
struct
en50221_mmi_object_t
{
int
i_object_type
;
union
{
struct
{
bool
b_blind
;
char
*
psz_text
;
}
enq
;
struct
{
bool
b_ok
;
char
*
psz_answ
;
}
answ
;
struct
{
char
*
psz_title
,
*
psz_subtitle
,
*
psz_bottom
;
char
**
ppsz_choices
;
int
i_choices
;
}
menu
;
/* menu and list are the same */
struct
{
int
i_choice
;
}
menu_answ
;
}
u
;
}
en50221_mmi_object_t
;
static
inline
void
en50221_MMIFree
(
en50221_mmi_object_t
*
p_object
)
{
int
i
;
switch
(
p_object
->
i_object_type
)
{
case
EN50221_MMI_ENQ
:
FREENULL
(
p_object
->
u
.
enq
.
psz_text
);
break
;
case
EN50221_MMI_ANSW
:
if
(
p_object
->
u
.
answ
.
b_ok
)
{
FREENULL
(
p_object
->
u
.
answ
.
psz_answ
);
}
break
;
case
EN50221_MMI_MENU
:
case
EN50221_MMI_LIST
:
FREENULL
(
p_object
->
u
.
menu
.
psz_title
);
FREENULL
(
p_object
->
u
.
menu
.
psz_subtitle
);
FREENULL
(
p_object
->
u
.
menu
.
psz_bottom
);
for
(
i
=
0
;
i
<
p_object
->
u
.
menu
.
i_choices
;
i
++
)
{
free
(
p_object
->
u
.
menu
.
ppsz_choices
[
i
]
);
}
FREENULL
(
p_object
->
u
.
menu
.
ppsz_choices
);
break
;
default:
break
;
}
}
#define MAX_DEMUX 256
#define MAX_CI_SLOTS 16
#define MAX_SESSIONS 32
#define MAX_PROGRAMS 24
#include "en50221.h"
struct
access_sys_t
{
int
i_handle
,
i_frontend_handle
;
demux_handle_t
p_demux_handles
[
MAX_DEMUX
];
frontend_t
*
p_frontend
;
mtime_t
i_frontend_timeout
;
bool
b_budget_mode
;
/* CA management */
int
i_ca_handle
;
int
i_ca_type
;
int
i_nb_slots
;
bool
pb_active_slot
[
MAX_CI_SLOTS
];
bool
pb_tc_has_data
[
MAX_CI_SLOTS
];
bool
pb_slot_mmi_expected
[
MAX_CI_SLOTS
];
bool
pb_slot_mmi_undisplayed
[
MAX_CI_SLOTS
];
en50221_session_t
p_sessions
[
MAX_SESSIONS
];
mtime_t
i_ca_timeout
,
i_ca_next_event
,
i_frontend_timeout
;
dvbpsi_pmt_t
*
pp_selected_programs
[
MAX_PROGRAMS
];
int
i_selected_programs
;
cam_t
cam
;
/* */
int
i_read_once
;
...
...
@@ -220,19 +126,6 @@ void CAMClose( access_t * );
void
CAMStatus
(
access_t
*
);
#endif
int
en50221_Init
(
access_t
*
);
int
en50221_Poll
(
access_t
*
);
int
en50221_SetCAPMT
(
access_t
*
,
dvbpsi_pmt_t
*
);
int
en50221_OpenMMI
(
access_t
*
p_access
,
int
i_slot
);
int
en50221_CloseMMI
(
access_t
*
p_access
,
int
i_slot
);
en50221_mmi_object_t
*
en50221_GetMMIObject
(
access_t
*
p_access
,
int
i_slot
);
void
en50221_SendMMIObject
(
access_t
*
p_access
,
int
i_slot
,
en50221_mmi_object_t
*
p_object
);
void
en50221_End
(
access_t
*
);
char
*
dvbsi_to_utf8
(
const
char
*
psz_instring
,
size_t
i_length
);
#ifdef ENABLE_HTTPD
int
HTTPOpen
(
access_t
*
p_access
);
void
HTTPClose
(
access_t
*
p_access
);
...
...
modules/access/dvb/en50221.c
View file @
3c83efbe
This diff is collapsed.
Click to expand it.
modules/access/dvb/en50221.h
0 → 100644
View file @
3c83efbe
/*****************************************************************************
* en50221.h:
*****************************************************************************
* Copyright (C) 1998-2010 the VideoLAN team
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
* Christopher Ross <chris@tebibyte.org>
* Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
typedef
struct
cam
cam_t
;
typedef
struct
en50221_session_t
{
unsigned
i_slot
;
int
i_resource_id
;
void
(
*
pf_handle
)(
cam_t
*
,
int
,
uint8_t
*
,
int
);
void
(
*
pf_close
)(
cam_t
*
,
int
);
void
(
*
pf_manage
)(
cam_t
*
,
int
);
void
*
p_sys
;
}
en50221_session_t
;
#define EN50221_MMI_NONE 0
#define EN50221_MMI_ENQ 1
#define EN50221_MMI_ANSW 2
#define EN50221_MMI_MENU 3
#define EN50221_MMI_MENU_ANSW 4
#define EN50221_MMI_LIST 5
typedef
struct
en50221_mmi_object_t
{
int
i_object_type
;
union
{
struct
{
bool
b_blind
;
char
*
psz_text
;
}
enq
;
struct
{
bool
b_ok
;
char
*
psz_answ
;
}
answ
;
struct
{
char
*
psz_title
,
*
psz_subtitle
,
*
psz_bottom
;
char
**
ppsz_choices
;
int
i_choices
;
}
menu
;
/* menu and list are the same */
struct
{
int
i_choice
;
}
menu_answ
;
}
u
;
}
en50221_mmi_object_t
;
static
inline
void
en50221_MMIFree
(
en50221_mmi_object_t
*
p_object
)
{
int
i
;
switch
(
p_object
->
i_object_type
)
{
case
EN50221_MMI_ENQ
:
FREENULL
(
p_object
->
u
.
enq
.
psz_text
);
break
;
case
EN50221_MMI_ANSW
:
if
(
p_object
->
u
.
answ
.
b_ok
)
{
FREENULL
(
p_object
->
u
.
answ
.
psz_answ
);
}
break
;
case
EN50221_MMI_MENU
:
case
EN50221_MMI_LIST
:
FREENULL
(
p_object
->
u
.
menu
.
psz_title
);
FREENULL
(
p_object
->
u
.
menu
.
psz_subtitle
);
FREENULL
(
p_object
->
u
.
menu
.
psz_bottom
);
for
(
i
=
0
;
i
<
p_object
->
u
.
menu
.
i_choices
;
i
++
)
{
free
(
p_object
->
u
.
menu
.
ppsz_choices
[
i
]
);
}
FREENULL
(
p_object
->
u
.
menu
.
ppsz_choices
);
break
;
default:
break
;
}
}
/* CA management */
#define MAX_CI_SLOTS 16
#define MAX_SESSIONS 32
#define MAX_PROGRAMS 24
struct
cam
{
vlc_object_t
*
obj
;
int
i_ca_type
;
int
fd
;
mtime_t
i_timeout
,
i_next_event
;
unsigned
i_nb_slots
;
bool
pb_active_slot
[
MAX_CI_SLOTS
];
bool
pb_tc_has_data
[
MAX_CI_SLOTS
];
bool
pb_slot_mmi_expected
[
MAX_CI_SLOTS
];
bool
pb_slot_mmi_undisplayed
[
MAX_CI_SLOTS
];
en50221_session_t
p_sessions
[
MAX_SESSIONS
];
dvbpsi_pmt_t
*
pp_selected_programs
[
MAX_PROGRAMS
];
int
i_selected_programs
;
};
int
en50221_Init
(
cam_t
*
);
int
en50221_Poll
(
cam_t
*
);
int
en50221_SetCAPMT
(
cam_t
*
,
dvbpsi_pmt_t
*
);
int
en50221_OpenMMI
(
cam_t
*
,
unsigned
i_slot
);
int
en50221_CloseMMI
(
cam_t
*
,
unsigned
i_slot
);
en50221_mmi_object_t
*
en50221_GetMMIObject
(
cam_t
*
,
unsigned
i_slot
);
void
en50221_SendMMIObject
(
cam_t
*
,
unsigned
i_slot
,
en50221_mmi_object_t
*
);
void
en50221_End
(
cam_t
*
);
char
*
dvbsi_to_utf8
(
const
char
*
psz_instring
,
size_t
i_length
);
modules/access/dvb/http.c
View file @
3c83efbe
...
...
@@ -242,7 +242,7 @@ static int HttpCallback( httpd_file_sys_t *p_args,
p_sys
->
i_httpd_timeout
=
mdate
()
+
INT64_C
(
3000000
);
/* 3 s */
p_sys
->
psz_request
=
psz_request
;
p_sys
->
b_request_frontend_info
=
true
;
if
(
p_sys
->
i_ca_handle
)
if
(
p_sys
->
cam
.
fd
!=
-
1
)
{
p_sys
->
b_request_mmi_info
=
true
;
}
...
...
modules/access/dvb/linux_dvb.c
View file @
3c83efbe
...
...
@@ -1462,11 +1462,13 @@ void DVRClose( access_t * p_access )
*****************************************************************************/
int
CAMOpen
(
access_t
*
p_access
)
{
access_sys_t
*
p_sys
=
p_access
->
p_sys
;
cam_t
*
p_cam
=
&
p_access
->
p_sys
->
cam
;
char
ca
[
128
];
int
i_adapter
,
i_device
;
ca_caps_t
caps
;
p_cam
->
obj
=
VLC_OBJECT
(
p_access
);
i_adapter
=
var_GetInteger
(
p_access
,
"dvb-adapter"
);
i_device
=
var_GetInteger
(
p_access
,
"dvb-device"
);
...
...
@@ -1478,19 +1480,17 @@ int CAMOpen( access_t *p_access )
memset
(
&
caps
,
0
,
sizeof
(
ca_caps_t
));
msg_Dbg
(
p_access
,
"Opening device %s"
,
ca
);
if
(
(
p_sys
->
i_ca_handle
=
vlc_open
(
ca
,
O_RDWR
|
O_NONBLOCK
))
<
0
)
p_cam
->
fd
=
vlc_open
(
ca
,
O_RDWR
|
O_NONBLOCK
);
if
(
p_cam
->
fd
==
-
1
)
{
msg_Warn
(
p_access
,
"CAMInit: opening CAM device failed (%m)"
);
p_sys
->
i_ca_handle
=
0
;
return
VLC_EGENERIC
;
}
if
(
ioctl
(
p_
sys
->
i_ca_handle
,
CA_GET_CAP
,
&
caps
)
!=
0
)
if
(
ioctl
(
p_
cam
->
fd
,
CA_GET_CAP
,
&
caps
)
<
0
)
{
msg_Err
(
p_access
,
"CAMInit: ioctl() error getting CAM capabilities"
);
close
(
p_sys
->
i_ca_handle
);
p_sys
->
i_ca_handle
=
0
;
return
VLC_EGENERIC
;
goto
error
;
}
/* Output CA capabilities */
...
...
@@ -1519,35 +1519,35 @@ int CAMOpen( access_t *p_access )
if
(
caps
.
slot_num
==
0
)
{
msg_Err
(
p_access
,
"CAMInit: CAM module with no slots"
);
close
(
p_sys
->
i_ca_handle
);
p_sys
->
i_ca_handle
=
0
;
return
VLC_EGENERIC
;
goto
error
;
}
if
(
caps
.
slot_type
&
CA_CI_LINK
)
{
p_
sys
->
i_ca_type
=
CA_CI_LINK
;
p_
cam
->
i_ca_type
=
CA_CI_LINK
;
}
else
if
(
caps
.
slot_type
&
CA_CI
)
{
p_
sys
->
i_ca_type
=
CA_CI
;
p_
cam
->
i_ca_type
=
CA_CI
;
}
else
{
p_
sys
->
i_ca_type
=
-
1
;
p_
cam
->
i_ca_type
=
-
1
;
msg_Err
(
p_access
,
"CAMInit: incompatible CAM interface"
);
close
(
p_sys
->
i_ca_handle
);
p_sys
->
i_ca_handle
=
0
;
return
VLC_EGENERIC
;
goto
error
;
}
p_
sys
->
i_nb_slots
=
caps
.
slot_num
;
memset
(
p_
sys
->
pb_active_slot
,
0
,
sizeof
(
bool
)
*
MAX_CI_SLOTS
);
memset
(
p_
sys
->
pb_slot_mmi_expected
,
0
,
sizeof
(
bool
)
*
MAX_CI_SLOTS
);
memset
(
p_
sys
->
pb_slot_mmi_undisplayed
,
0
,
p_
cam
->
i_nb_slots
=
caps
.
slot_num
;
memset
(
p_
cam
->
pb_active_slot
,
0
,
sizeof
(
bool
)
*
MAX_CI_SLOTS
);
memset
(
p_
cam
->
pb_slot_mmi_expected
,
0
,
sizeof
(
bool
)
*
MAX_CI_SLOTS
);
memset
(
p_
cam
->
pb_slot_mmi_undisplayed
,
0
,
sizeof
(
bool
)
*
MAX_CI_SLOTS
);
return
en50221_Init
(
p_access
);
return
en50221_Init
(
p_cam
);
error:
close
(
p_cam
->
fd
);
p_cam
->
fd
=
-
1
;
return
VLC_EGENERIC
;
}
/*****************************************************************************
...
...
@@ -1555,28 +1555,25 @@ int CAMOpen( access_t *p_access )
*****************************************************************************/
int
CAMPoll
(
access_t
*
p_access
)
{
access_sys_t
*
p_sys
=
p_access
->
p_sys
;
int
i_ret
=
VLC_EGENERIC
;
cam_t
*
p_cam
=
&
p_access
->
p_sys
->
cam
;
if
(
p_sys
->
i_ca_handle
==
0
)
{
if
(
p_cam
->
fd
==
-
1
)
return
VLC_EGENERIC
;
}
switch
(
p_
sys
->
i_ca_type
)
switch
(
p_
cam
->
i_ca_type
)
{
case
CA_CI_LINK
:
i_ret
=
en50221_Poll
(
p_access
);
break
;
if
(
mdate
()
>
p_cam
->
i_next_event
)
{
int
ret
=
en50221_Poll
(
p_cam
);
p_cam
->
i_next_event
=
mdate
()
+
p_cam
->
i_timeout
;
return
ret
;
}
case
CA_CI
:
i_ret
=
VLC_SUCCESS
;
break
;
default:
msg_Err
(
p_access
,
"CAMPoll: This should not happen"
);
break
;
return
VLC_SUCCESS
;
}
return
i_ret
;
msg_Err
(
p_access
,
"CAMPoll: This should not happen"
);
return
VLC_EGENERIC
;
;
}
#ifdef ENABLE_HTTPD
...
...
@@ -1586,17 +1583,18 @@ int CAMPoll( access_t * p_access )
void
CAMStatus
(
access_t
*
p_access
)
{
access_sys_t
*
p_sys
=
p_access
->
p_sys
;
cam_t
*
p_cam
=
&
p_sys
->
cam
;
char
*
p
;
ca_caps_t
caps
;
int
i
_slot
,
i
;
int
i
;
if
(
p_sys
->
psz_request
!=
NULL
&&
*
p_sys
->
psz_request
)
{
/* Check if we have an undisplayed MMI message : in that case we ignore
* the user input to avoid confusing the CAM. */
for
(
i_slot
=
0
;
i_slot
<
p_sys
->
i_nb_slots
;
i_slot
++
)
for
(
unsigned
i_slot
=
0
;
i_slot
<
p_cam
->
i_nb_slots
;
i_slot
++
)
{
if
(
p_
sys
->
pb_slot_mmi_undisplayed
[
i_slot
]
==
true
)
if
(
p_
cam
->
pb_slot_mmi_undisplayed
[
i_slot
]
==
true
)
{
p_sys
->
psz_request
=
NULL
;
msg_Dbg
(
p_access
,
...
...
@@ -1628,14 +1626,14 @@ void CAMStatus( access_t * p_access )
if
(
HTTPExtractValue
(
psz_request
,
"open"
,
psz_value
,
sizeof
(
psz_value
)
)
!=
NULL
)
{
en50221_OpenMMI
(
p_
access
,
i_slot
);
en50221_OpenMMI
(
p_
cam
,
i_slot
);
return
;
}
if
(
HTTPExtractValue
(
psz_request
,
"close"
,
psz_value
,
sizeof
(
psz_value
)
)
!=
NULL
)
{
en50221_CloseMMI
(
p_
access
,
i_slot
);
en50221_CloseMMI
(
p_
cam
,
i_slot
);
return
;
}
...
...
@@ -1689,20 +1687,20 @@ void CAMStatus( access_t * p_access )
}
}
en50221_SendMMIObject
(
p_
access
,
i_slot
,
&
mmi_object
);
en50221_SendMMIObject
(
p_
cam
,
i_slot
,
&
mmi_object
);
return
;
}
/* Check that we have all necessary MMI information. */
for
(
i_slot
=
0
;
i_slot
<
p_sys
->
i_nb_slots
;
i_slot
++
)
for
(
unsigned
i_slot
=
0
;
i_slot
<
p_cam
->
i_nb_slots
;
i_slot
++
)
{
if
(
p_
sys
->
pb_slot_mmi_expected
[
i_slot
]
==
true
)
if
(
p_
cam
->
pb_slot_mmi_expected
[
i_slot
]
==
true
)
return
;
}
p
=
p_sys
->
psz_mmi_info
=
malloc
(
10000
);
if
(
ioctl
(
p_
sys
->
i_ca_handle
,
CA_GET_CAP
,
&
caps
)
!=
0
)
if
(
ioctl
(
p_
cam
->
fd
,
CA_GET_CAP
,
&
caps
)
!=
0
)
{
char
buf
[
1000
];
strerror_r
(
errno
,
buf
,
sizeof
(
buf
)
);
...
...
@@ -1737,15 +1735,15 @@ void CAMStatus( access_t * p_access )
p
+=
sprintf
(
p
,
"</table>"
);
for
(
i_slot
=
0
;
i_slot
<
p_sys
->
i_nb_slots
;
i_slot
++
)
for
(
unsigned
i_slot
=
0
;
i_slot
<
p_cam
->
i_nb_slots
;
i_slot
++
)
{
ca_slot_info_t
sinfo
;
p_
sys
->
pb_slot_mmi_undisplayed
[
i_slot
]
=
false
;
p_
cam
->
pb_slot_mmi_undisplayed
[
i_slot
]
=
false
;
p
+=
sprintf
(
p
,
"<p>CA slot #%d: "
,
i_slot
);
sinfo
.
num
=
i_slot
;
if
(
ioctl
(
p_
sys
->
i_ca_handle
,
CA_GET_SLOT_INFO
,
&
sinfo
)
!=
0
)
if
(
ioctl
(
p_
cam
->
fd
,
CA_GET_SLOT_INFO
,
&
sinfo
)
!=
0
)
{
char
buf
[
1000
];
strerror_r
(
errno
,
buf
,
sizeof
(
buf
)
);
...
...
@@ -1764,7 +1762,7 @@ void CAMStatus( access_t * p_access )
if
(
sinfo
.
flags
&
CA_CI_MODULE_READY
)
{
en50221_mmi_object_t
*
p_object
=
en50221_GetMMIObject
(
p_
access
,
en50221_mmi_object_t
*
p_object
=
en50221_GetMMIObject
(
p_
cam
,
i_slot
);
p
+=
sprintf
(
p
,
"module present and ready<p>
\n
"
);
...
...
@@ -1845,15 +1843,15 @@ out:
*****************************************************************************/
int
CAMSet
(
access_t
*
p_access
,
dvbpsi_pmt_t
*
p_pmt
)
{
access_sys_t
*
p_sys
=
p_access
->
p_sys
;
cam_t
*
p_cam
=
&
p_access
->
p_sys
->
cam
;
if
(
p_
sys
->
i_ca_handle
==
0
)
if
(
p_
cam
->
fd
==
-
1
)
{
dvbpsi_DeletePMT
(
p_pmt
);
return
VLC_EGENERIC
;
}
en50221_SetCAPMT
(
p_
access
,
p_pmt
);
en50221_SetCAPMT
(
p_
cam
,
p_pmt
);
return
VLC_SUCCESS
;
}
...
...
@@ -1863,13 +1861,11 @@ int CAMSet( access_t * p_access, dvbpsi_pmt_t *p_pmt )
*****************************************************************************/
void
CAMClose
(
access_t
*
p_access
)
{
access_sys_t
*
p_sys
=
p_access
->
p_sys
;
cam_t
*
p_cam
=
&
p_access
->
p_sys
->
cam
;
en50221_End
(
p_access
);
if
(
p_cam
->
fd
==
-
1
)
return
;
if
(
p_sys
->
i_ca_handle
)
{
close
(
p_sys
->
i_ca_handle
);
}
en50221_End
(
p_cam
);
close
(
p_cam
->
fd
);
}
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