Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot set device class #18

Open
schell opened this issue Nov 16, 2020 · 3 comments
Open

Cannot set device class #18

schell opened this issue Nov 16, 2020 · 3 comments

Comments

@schell
Copy link

schell commented Nov 16, 2020

Thank you for this nice crate. When trying to set up my rpi as a bluetooth keyboard I run into the following error, specifically while setting the device class:

Error: Xfer { source: Bluez { source: CommandError { opcode: SetDeviceClass, status: InvalidParams } } }

Where Xfer is my own Error enum.

This is roughly my program:

pub async fn run() -> Result<(), Error> {
    let mut client = BlueZClient::new().unwrap();

    let version = client.get_mgmt_version().await?;
    trace!(
        "management version: {}.{}",
        version.version,
        version.revision
    );

    let controllers = client.get_ext_controller_list().await?;
    let (controller, type_is, bus) = controllers.first().with_context(|| NoControllers)?;
    trace!(
        "got controller:\n{:?} ({:?}, {:?})",
        controller,
        type_is,
        bus
    );
    trace!(
        "info:\n{:#?}",
        client.get_controller_info(*controller).await?
    );

    let ctrl_settings = client
        .set_powered(
            *controller,
            true
        )
        .await?;
    trace!("controller settings after power on: {:?}", ctrl_settings);

    let ctrl_settings = client
        .set_connectable(
            *controller,
            true
        )
        .await?;
    trace!("controller settings after connectable: {:?}", ctrl_settings);

    let ctrl_settings = client
        .set_discoverable(
            *controller,
            DiscoverableMode::Limited,
            Some(60)
        )
        .await?;
    trace!("controller settings after discoverable: {:?}", ctrl_settings);

    let return_classes = client
        .set_device_class(
            *controller,
            DeviceClass::Peripheral {
                keyboard: true,
                pointer: false,
                class: PeripheralDeviceClass::Uncategorized,
            },
        )
        .await?;

    trace!("set device class, got: {:?}", return_classes);
    Ok(())
}

It's notable however, that using the command line to set the device class is working:

sudo hciconfig hci0 class 0x002540

After running the cli above, the settings have properly updated:

ControllerInfo {
    address: Address {
        bytes: [
            248,
            250,
            50,
            235,
            39,
            184,
        ],
    },
    bluetooth_version: 7,
    manufacturer: 15,
    supported_settings: BitFlags<ControllerSetting> {
        bits: 0b11011111111111111,
        flags: Powered | Connectable | FastConnectable | Discoverable | Pairable | LinkLevelSecurity | SecureSimplePairing | BREDR | HighSpeed | LE | Advertising | SecureConnection | DebugKeys | Privacy | StaticAddress | PhyConfiguration,
    },
    current_settings: BitFlags<ControllerSetting> {
        bits: 0b101011010011,
        flags: Powered | Connectable | Pairable | SecureSimplePairing | BREDR | LE | SecureConnection,
    },
    class_of_device: (
        Peripheral {
            keyboard: true,
            pointer: false,
            class: Uncategorized,
        },
        BitFlags<ServiceClass> {
            bits: 0b0,
        },
    ),
    name: "raspberrypi",
    short_name: "",
}

I'm new to working with bluetooth so I'm not sure what the problem is, but I thought it might be that the DeviceClass wasn't being converted into the correct u16 - indeed my device class seems to convert to 0x540, but making exec_command public and calling it with an explicit class of 0x2540 encounters the same error.

@laptou
Copy link
Owner

laptou commented Nov 21, 2020

It is unclear why this is not working. The BlueZ documentation doesn't give any information about why 0x540 might be an invalid device class, and neither does the Bluetooth website.

@schell
Copy link
Author

schell commented Nov 21, 2020

Yes, it seems weird. In the meantime I'm using the cli as a backup.

@schell
Copy link
Author

schell commented Nov 23, 2020

I think it's notable that the 0x2000 part of 0x2540 sets the device in limited discovery mode. I thought maybe the problem was that setting 0x540 when the device is not already in limited discover would result in an invalid param error, so I set the device explicitly in limited discovery by first using set_discoverable. This doesn't seem to remedy the situation, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants