litra-driver icon indicating copy to clipboard operation
litra-driver copied to clipboard

Different idProduct for the Litra Beam

Open sagarbehere opened this issue 2 years ago • 1 comments

Thank you for making this software. I just got a Litra Beam which is very similar to the Litra Glow. So I am optimistic that this software will work for the Litra Beam as well. The output of the lsusb command shows the following for the Litra Beam

Bus 001 Device 113: ID 046d:c901 Logitech, Inc. Litra Beam

As far as I can tell, the only change that should be necessary is that the udev rule should mention ATTR{idProduct}=="c901" instead of "c900". However, I also noticed that the c900 is hard coded as the PRODUCT_ID in src/llgd/lib/llgd_lib.py. Is there a way to specify the product id via the command line or a config file, so that this will work with the Litra Beam too?

Thanks in advance.

sagarbehere avatar Sep 29 '22 04:09 sagarbehere

I'd also love this for my beam please!

henricook avatar Oct 03 '22 08:10 henricook

@kharyam Do you think this could be added, if you have time?

henricook avatar Nov 23 '22 09:11 henricook

Hey @sagarbehere and @henricook - this fell off my radar but I'll try to get to it in the next few days. Thanks!

kharyam avatar Dec 02 '22 16:12 kharyam

@sagarbehere @henricook I just released a new version that should hopefully support the beam seamlessly (no config file or command line options needed). Please let me know your results whenever you get a chance to test as I don't have a Litra Beam. Thanks!

kharyam avatar Dec 06 '22 02:12 kharyam

Merry Christmas to me 🎉 - I'll try it on my next reboot!

henricook avatar Dec 06 '22 10:12 henricook

Thanks @kharyam for the patch. Unfortunately it looks like that it is not working on my setup: This is the output of lc on command.

$ lc on 


Traceback (most recent call last):
  File "/home/sonic/.local/lib/python3.10/site-packages/usb/core.py", line 236, in get_interface_and_endpoint
    return self._ep_info[endpoint_address]
KeyError: 2

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/sonic/.local/bin/lc", line 8, in <module>
    sys.exit(main())
  File "/home/sonic/.local/lib/python3.10/site-packages/llgd/cli/cli.py", line 77, in main
    fire.Fire({
  File "/home/sonic/.local/lib/python3.10/site-packages/fire/core.py", line 141, in Fire
    component_trace = _Fire(component, args, parsed_flag_args, context, name)
  File "/home/sonic/.local/lib/python3.10/site-packages/fire/core.py", line 466, in _Fire
    component, remaining_args = _CallAndUpdateTrace(
  File "/home/sonic/.local/lib/python3.10/site-packages/fire/core.py", line 681, in _CallAndUpdateTrace
    component = fn(*varargs, **kwargs)
  File "/home/sonic/.local/lib/python3.10/site-packages/llgd/cli/cli.py", line 28, in on
    light_on()
  File "/home/sonic/.local/lib/python3.10/site-packages/llgd/lib/llgd_lib.py", line 85, in light_on
    dev.write(0x02, [0x11, 0xff, 0x04, 0x1c, LIGHT_ON, 0x00, 0x00, 0x00, 0x00, 0x00,
  File "/home/sonic/.local/lib/python3.10/site-packages/usb/core.py", line 986, in write
    intf, ep = self._ctx.setup_request(self, endpoint)
  File "/home/sonic/.local/lib/python3.10/site-packages/usb/core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "/home/sonic/.local/lib/python3.10/site-packages/usb/core.py", line 228, in setup_request
    intf, ep = self.get_interface_and_endpoint(device, endpoint_address)
  File "/home/sonic/.local/lib/python3.10/site-packages/usb/core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "/home/sonic/.local/lib/python3.10/site-packages/usb/core.py", line 244, in get_interface_and_endpoint
    raise ValueError('Invalid endpoint address ' + hex(endpoint_address))
ValueError: Invalid endpoint address 0x2

massimeddu-sj avatar Dec 06 '22 10:12 massimeddu-sj

Hi @kharyam , unfortunately I don't have my Litra Beam any more, so I won't be able to test this. Apologies.

sagarbehere avatar Dec 06 '22 11:12 sagarbehere

I'm seeing the same error as @massimeddu-sonicjobs is any of this lsusb -v output helpful?

Bus 001 Device 002: ID 046d:c901 Logitech, Inc. Litra Beam
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x046d Logitech, Inc.
  idProduct          0xc901 
  bcdDevice            1.00
  iManufacturer           1 Logitech
  iProduct                2 Litra Beam
  iSerial                 3 2232FE701SD8
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0029
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      89
          Report Descriptor: (length is 89)
            Item(Global): Usage Page, data= [ 0x0c ] 12
                            Consumer
            Item(Local ): Usage, data= [ 0x01 ] 1
                            Consumer Control
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Main  ): Collection, data= [ 0x03 ] 3
                            Report
            Item(Local ): Usage, data= [ 0x30 ] 48
                            Power
            Item(Global): Report ID, data= [ 0x01 ] 1
            Item(Global): Logical Minimum, data= [ 0xff ] 255
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x02 ] 2
            Item(Main  ): Output, data= [ 0x26 ] 38
                            Data Variable Relative No_Wrap Linear
                            No_Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x1f ] 31
                            (null)
            Item(Main  ): Input, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x06 ] 6
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Output, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x1f ] 31
                            (null)
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Main  ): Collection, data= [ 0x03 ] 3
                            Report
            Item(Local ): Usage, data= [ 0x30 ] 48
                            Power
            Item(Global): Report ID, data= [ 0x02 ] 2
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Output, data= [ 0x06 ] 6
                            Data Variable Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x07 ] 7
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Output, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Main  ): End Collection, data=none
            Item(Global): Usage Page, data= [ 0x43 0xff ] 65347
                            (null)
            Item(Local ): Usage, data= [ 0x02 0x02 ] 514
                            (null)
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x11 ] 17
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x13 ] 19
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Local ): Usage, data= [ 0x02 ] 2
                            (null)
            Item(Main  ): Input, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x02 ] 2
                            (null)
            Item(Main  ): Output, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
can't get device qualifier: Resource temporarily unavailable
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

henricook avatar Dec 07 '22 08:12 henricook

Thanks @massimeddu-sonicjobs @henricook - it looks like the beam uses different control codes than the glow for some reason. I'll check whether the lsusb -v output provides any hints otherwise I'll have to see if I can get my hands on a beam.

kharyam avatar Dec 07 '22 15:12 kharyam

It looks like the endpoint address is different for the Beam. I'll use the correct endpoint address depending on the device and push that code later today :crossed_fingers:

kharyam avatar Dec 07 '22 16:12 kharyam

@henricook @massimeddu-sonicjobs - I just pushed a new version to pypi with the correct endpoint for the Beam. Hopefully the rest of the API is the same as the Glow - let me know how it goes whenever you get a chance.

kharyam avatar Dec 07 '22 23:12 kharyam

Hi @kharyam , it looks like that the litra beam also have a different buffer size for the read operations. I've created a PR that solves the issue on my setup: https://github.com/kharyam/litra-driver/pull/25

With the additional fix, everything looks working perfectly.

Thank you!

massimeddu-sj avatar Dec 08 '22 10:12 massimeddu-sj

Great find @massimeddu-sonicjobs ! just merged and pushed a new release

cc: @henricook

kharyam avatar Dec 08 '22 15:12 kharyam

Glorious! Works for me as well - thanks so much @kharyam !

henricook avatar Dec 08 '22 20:12 henricook

Thanks for the help getting this one implemented!

kharyam avatar Dec 08 '22 22:12 kharyam