Pulse-Eight / libcec

USB CEC Adapter communication Library http://libcec.pulse-eight.com/
Other
705 stars 282 forks source link

libcecc_initialise failure #607

Open ErikTerwan opened 1 year ago

ErikTerwan commented 1 year ago

I have this code, which runs beatifully on a Raspberry Pi 3B with Raspberry Pi OS (buster):

libcecc_reset_configuration(&g_config);
g_config.clientVersion = LIBCEC_VERSION_CURRENT;
g_config.bActivateSource = 0;
g_callbacks.commandReceived = command_received_callback;
g_callbacks.keyPress = key_press_callback;
g_callbacks.configurationChanged = configuration_changed_callback;
g_config.callbacks = &g_callbacks;
g_config.deviceTypes.types[0] = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
snprintf(g_config.strDeviceName, sizeof (g_config.strDeviceName), "ETHA");

if (libcecc_initialise(&g_config, &g_iface, NULL) != 1) {
    fprintf(stderr, __FILE__": libcecc_initialise() failed!\n");
    return -1;
}

Now I'm rebuilding that system to Raspberry Pi OS (bullseye) with the vc4-kms-v3d video driver (default configuration) and libcec-dev=6.0.2-2+rpt2 installed, but now the call to libcecc_initialise fails.

Output cec-client -l (bullseye):

libCEC version: 6.0.2, compiled on Linux-5.10.63-v8+ ... , features: P8_USB, DRM, P8_detect, randr, RPi, Exynos, Linux, AOCEC
Found devices: 1

device:              1
com port:            /dev/cec0
vendor id:           0000
product id:          0000
firmware version:    0
type:                Linux

Same on buster:

libCEC version: 5.0.0, git revision: libcec-4.0.4+61-4ef0486, compiled on 2020-05-16 16:22:20 by root@etha on Linux 4.19.97-v7+ (armv7l), features: P8_USB, DRM, P8_detect, randr, RPi
Found devices: 1

device:              1
com port:            RPI
vendor id:           2708
product id:          1001
firmware version:    1
type:                Raspberry Pi

Please help!

ErikTerwan commented 1 year ago

Tried again with the vc4-fkms-v3d video driver. No luck, but the output of cec-client -l seems to match that of buster:

libCEC version: 6.0.2, compiled on Linux-5.10.63-v8+ ... , features: P8_USB, DRM, P8_detect, randr, RPi, Exynos, Linux, AOCEC
Found devices: 1

device:              1
com port:            RPI
vendor id:           2708
product id:          1001
firmware version:    1
type:                Raspberry Pi
ErikTerwan commented 1 year ago

Furthermore (back on the vc4-kms-v3d video driver) cec-client seems to work properly:

echo 'scan' | cec-client -s -d 1
opening a connection to the CEC adapter...
requesting CEC bus information ...
ERROR:   [            7753] failed to request the physical address
CEC bus information
===================
device #0: TV
address:       0.0.0.0
active source: no
vendor:        Philips
osd string:    TV
CEC version:   1.4
power status:  on
language:      dut

device #1: Recorder 1
address:       1.3.0.0
active source: yes
vendor:        Philips
osd string:    CECTester
CEC version:   1.4
power status:  on
language:      eng

device #4: Playback 1
address:       f.f.f.f
active source: no
vendor:        Broadcom
osd string:    raspberry
CEC version:   1.3a
power status:  on
language:      eng

device #5: Audio
address:       1.0.0.0
active source: no
vendor:        Onkyo
osd string:    TX-NR515
CEC version:   1.4
power status:  on
language:      ???

currently active source: Recorder 1 (1)

But I see no difference between my code and the cec-client code (other than the difference between C and C++):

g_config.Clear();
  g_callbacks.Clear();
  snprintf(g_config.strDeviceName, LIBCEC_OSD_NAME_SIZE, "CECTester");
  g_config.clientVersion      = LIBCEC_VERSION_CURRENT;
  g_config.bActivateSource    = 0;
  g_callbacks.logMessage      = &CecLogMessage;
  g_callbacks.keyPress        = &CecKeyPress;
  g_callbacks.commandReceived = &CecCommand;
  g_callbacks.alert           = &CecAlert;
  g_config.callbacks          = &g_callbacks;

  if (!ProcessCommandLineArguments(argc, argv))
    return 0;

  if (g_cecLogLevel == -1)
    g_cecLogLevel = g_cecDefaultLogLevel;

  if (g_config.deviceTypes.IsEmpty())
  {
    if (!g_bSingleCommand)
      std::cout << "No device type given. Using 'recording device'" << std::endl;
    g_config.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
  }

  g_parser = LibCecInitialise(&g_config);
  if (!g_parser)
  {

So is there a difference between the two languages (macro expansion, code)?

ErikTerwan commented 1 year ago

To summarize: this C++ program works (no Error! printed):

#include <iostream>

#include "/usr/include/libcec/cec.h"

using namespace CEC;

#include "/usr/include/libcec/cecloader.h"

libcec_configuration    g_config;
ICECAdapter*        g_parser;

int main (int argc, char *argv[]) {

    g_config.Clear();
    snprintf(g_config.strDeviceName, LIBCEC_OSD_NAME_SIZE, "Test");
    g_config.clientVersion = LIBCEC_VERSION_CURRENT;
    g_config.bActivateSource = 0;

    g_parser = LibCecInitialise(&g_config);
    if (!g_parser) {
        std::cout << "Error!" << std::endl;
    }

}

but this C program doesn't (Error! printed):

#include "/usr/include/libcec/ceccloader.h"

libcec_configuration g_config;
libcec_interface_t g_iface;

int main(int argc, char** argv) {

    libcecc_reset_configuration(&g_config);
    g_config.clientVersion = LIBCEC_VERSION_CURRENT;
    g_config.bActivateSource = 0;
    g_config.deviceTypes.types[0] = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
    snprintf(g_config.strDeviceName, sizeof (g_config.strDeviceName), "Test");

    if (libcecc_initialise(&g_config, &g_iface, NULL) != 1) {
        printf("Error!\n");
    }

}
ErikTerwan commented 1 year ago

Digging deeper I found some changes in/deletions from/additions to functions in LibCECC.cpp that were not accounted for in ceccloader.h.

libcec_enable_callbacks was removed in version 5, and replaced with libcec_set_callbacks and libcec_disable_callbacks (according to libcec/debian/changelog.in), although libcec_disable_callbacks is nowhere to be found.

libcec_can_persist_configuration was also removed in version 5, and replaced with libcec_can_save_configuration.

libcec_persist_configuration was removed in version 5 altogether.

So I updated ceccloader.h to reflect the current situation:

69a70,73
> #if CEC_LIB_VERSION_MAJOR >= 5
>   int                                 (CDECL *set_callbacks)(libcec_connection_t connection, void* cbParam, CEC_NAMESPACE ICECCallbacks* callbacks);
> //  int                                 (CDECL *disable_callbacks)(libcec_connection_t connection);
> # else
70a75
> #endif
108a114,118
> #if CEC_LIB_VERSION_MAJOR >= 5
>   int                                 (CDECL *can_save_configuration)(libcec_connection_t connection);
> #else
>   int                                 (CDECL *can_persist_configuration)(libcec_connection_t connection);
> #endif
146a157,160
> #if CEC_LIB_VERSION_MAJOR >= 5
>   _libcecc_resolve(lib, iface->set_callbacks,                 "libcec_set_callbacks",                 int(CDECL *)(libcec_connection_t, void*, CEC_NAMESPACE ICECCallbacks*));
> //  _libcecc_resolve(lib, iface->disable_callbacks,             "libcec_disable_callbacks",             int(CDECL *)(libcec_connection_t));
> #else
147a162
> # endif
184a200,202
> #if CEC_LIB_VERSION_MAJOR >= 5
>   _libcecc_resolve(lib, iface->can_save_configuration,        "libcec_can_save_configuration",        int(CDECL *)(libcec_connection_t));
> #else
186a205
> #endif

And now everything is running fine again.