#KeyMouse
1 messages ยท Page 1 of 1 (latest)
Anyway, it would be possible to make a custom USB Mouse-like device with this AC Pan report field, and write a custom driver that sends that value. For a tutorial on this, see https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/.
The stackoverflow thing you mentioned I think is for something else. Could you post the stackoverflow URL you got that from?
yes it's two separate keyboards each with a build in track ball. They somehow talk to each other, though there's only the usb from each of them to the pc
so I was hoping you were going to say that I could edit the adafruit_hid mouse file py file to add this functionality, and then continue on. Am I correct to conclude that if I want this feature I need to abandon circuit python for this project?
it should be possible; you'll probably need a bit of help on this. I will look at it later (not tonight)
I'm not in a hurry. I've been working on this project for literally year at this point.
So my son feel asleep early for once, so I've had some time to do some digging, I downloaded the full size hid python library files. In the keycodes file I see a like to a manual for the HID usage table for usb. AC Pan is definitely the correct one. https://usb.org/sites/default/files/hut1_21_0.pdf#page=83.
AC Pan Left Sel Display a portion of the document closer to the left margin of the document.
AC Pan Right Sel Display a portion of the document closer to the right margin of the document.
AC Pan LC Set the horizontal offset of the display in the document.
The way to do this is to take the parsed output of the descriptor and convert it to a definition to put in boot.py, as for example in https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/hid-devices#custom-hid-devices-3096614, substituting the fancy mouse for the gamepad in that example. The AC PAN value in the report looks like it's 8 bits, and is the last thing in the report. So you would take the Mouse.py code in the library and add another byte at the end of the report, and add one or more accessor functions to set the value. That is what I would do to test this idea.
So I think I am following. I need to create a file called boot.py. It will start before other files and setup my custom mouse "drive" as you call it. I am to mimic the file of the example gamepad. I've done that see attached file. I am not sure I got lines 50 correct I just added +1 to the number of bits in mentioned in mouse.py. Also line 55 and 57, and 58 I'd consider cutting, but I'm not confident about that
As far as modifying mouse.py itself. I see that the order from top to bottom is Usage Page (Button), Usage (X), Usage (Y), Usage (Wheel), Usage (AC Pan). That seems to line up with mouse.py order of bits. So I'm going to add a 5th bit to the mouse .py for pan. and everywhere the wheel or report 3 is mentions I'll mimic the code for pan. There is my attempt.
I guess all that's left to do is to load these files and see if they work... I added the boot file to my keyboard and nothing exploded so that's good and the mouse also is still working. so next to load the alternative mouse.py file
and when I load the new mouse.py files I get this error "ValueError: Buffer incorrect size. Should be 4 bytes."
so I guess that my boot.py is not working correctly
oh, I didn't change the gamepad = usb_hid.Device in boot. hmmm I'll try changing it to MOUSE, and deleting the keyboard and game pad mentions while I'm at it
there's the updated file
and... same error. probably i should use a different name for the device.
oh wait, that's calling for the usb_hid library, so if i delete that stuff in front maybe it'll work
and same error
I renames the device to mouse2, but I'm not sure how to change mouse.py and my code to try and reference this new device. I'm going to bed, have a good evening
tried running it again this afternoon and now the error has changes to OSError: USB busy. Not sure why the error changed...
I think it must be changing the name for MOUSE to mouse2, but it didn't implement until the device rebooted (because I'd powered off the PC)
It is one extra byte at the end of the mouse report. The size of the AC Pan value is 8 bits; the previous 8 mentioned for Wheel becomes the default for the following values until a new size is given.
0x09, 0x38, # Usage (Wheel)
0x25, 0x7F, # Logical Maximum (127)
0x75, 0x08, # Report Size (8)
0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x0C, # Usage Page (Consumer)
0x0A, 0x38, 0x02, # Usage (AC Pan)
0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
So you can create a new mouse.py like the one in the HID library. Maybe give it a different name and change the class name too. The report will be a bytearray(5) instead of a bytearray(4), and you'll add new methods for that extra byte for the AC Pan value.
your code looks ok
If I said "drive", that was a typo. I meant "device"
I'm still getting ValueError: Buffer incorrect size. Should be 4 bytes.
I tried changing usage=0x02, # Mouse to usage=0x05, # Gamepad in boot.py, still got the ValueError: Buffer incorrect size. Should be 4 bytes. Once I changed the value inself._mouse_device = find_device(devices, usage_page=0x1, usage=0x05) I got ValueError: Could not find matching HID device
could you give the backtrace for this? Also put your mouse2.py and test code somewhere (e.g. in a repo) or upload it so we can look at it
File "main.py", line 4, in <module>
File "pmw3389.py", line 9, in <module>
File "key_stroke.py", line 7, in <module>
File "/lib/adafruit_hid/mouse2.py", line 52, in __init__
File "/lib/adafruit_hid/mouse2.py", line 154, in _send_no_move
ValueError: Buffer incorrect size. Should be 4 bytes.```
there I just added it to github (never done that before) https://github.com/recurvehunt/Circuitpython-keyboard-and-mouse-in-a-single-device-
for test code I just modified my existing keyboard and mouse code. key_stoke.py is where in initial the mouse.
this is the other error I get (after unplugging and replugging pico back iin)Traceback (most recent call last): File "main.py", line 4, in <module> File "pmw3389.py", line 9, in <module> File "key_stroke.py", line 7, in <module> File "/lib/adafruit_hid/mouse2.py", line 55, in __init__ File "/lib/adafruit_hid/mouse2.py", line 154, in _send_no_move OSError: USB busy
I don't see mouse2.py in the repo. Not sure about the USB busy. Sometimes it helps to retry after a few seconds, because the host hasn't set up the USB devices immediately.
ops, forgot to add it since its under library, I've added it now
OK, so I think you are right that self._mouse_device = find_device(devices, usage_page=0x1, usage=0x02) is finding the default mouse device. In boot.py.
usb_hid.enable(
(usb_hid.Device.KEYBOARD,
usb_hid.Device.CONSUMER_CONTROL,
mouse2)
)
should not include the default mouse device. boot.py is run only after a hard reset or power cycle. So if you tried this without a reset, then you were getting the regular mouse device, not your customized one.
Okay that makes sense. So then the error we care about it at that point is the USB busy. That's the error I get if I actually power cycle. I'll double check that later but I'm about 95% positive.
ya I just tested it. when I powered it up (with all the "correct" code ) I get the usb bus error. I tried unplugging and using the "usb device clearing", but still got the same error. tried a couple times to restart as you said, but no chante.
I'm left thinking something is wrong with the boot.py file
look in boot_out.txt to see if there is an error reported in boot.py. Any errors are written to that file (since the serial output is not yet available)
Anything else I should try?
Here's a thought. Is it possible that since I've already got the exact same device description. Then that's the USB error? Like I already have a key mouse plugged in, so would a second device with the exact same description cause issues somehow?
i added a print statement at the out in boot.py just to make sure it was ok, and it printed.
also I found this https://github.com/adafruit/circuitpython/pull/118
looks like you dealt with this before and the answer was word aligned, though what word aligned means I have no idea
it does look like the device is showing up wrong in the device manager
That bug fix was the first work I ever did on CircuitPython. It is fixed long ago. It was an internal error having to do with the SAMD chips. A second KeyMouse should not make a difference. When I have time in the next day or two or maybe even tonight I will try your code.
I looked at your https://github.com/recurvehunt/Circuitpython-keyboard-and-mouse-in-a-single-device-/blob/main/boot.py more carefully. The KeyMouse HID report descriptor is a bit weird. The X and Y values are 12 bits each (so 1.5 bytes each, 3 bytes total). Also their Logical maximum is 2047, but the corresponding Logical minimum of -2048 is not given. Is this the descriptor straight out of the KeyMouse? Compare this with the more conventional mouse description in https://github.com/adafruit/circuitpython/blob/main/shared-module/usb_hid/Device.c#L89-L137 which uses 8-bit values -128 to +127. This is a bog-standard kind of mouse definition.
so in your descriptor, there is one byte for mouse buttons, 3 bytes for X and Y values, one byte for wheel, and one byte for AC Pan, 6 bytes total
Yes it came straight out of the mouse. That was only one of them though there were 5 per half keyboard. Only one mentioned pan so that was the one I used
here's another mouse hid device i found with pan https://gist.github.com/wararyo/770436ae6995665fb7e15b55699b86d0
Well i kept modifying that boot file until I got error to go away. This is what eventually "ran". No errors now just the mouse isn't actually working,...but it's late and I'm going to bed
This morning I tried implementing the reference hid for a mouse you linked to. And I couldn't get it to work
I found a different one online and tried it as well without success
could you upload the code.py you are using to test both your version and the reference version?
The main.py I see in your repo seems to be for something else
it's pmw3389.right_mouse.movement() in the main.py that's calling the mouse movement
and then in around line 170 in pmw3389.py code def movement(self): x, y = self.update_point() x = self.conv_twos_comp(x) y = self.conv_twos_comp(y) if not x == 0 or not y == 0: x, y = self.filter_movement(x, y) if pins.layer_2_key.value: mouse.move(0, 0, round(-x*0.13)) if abs(round(-y*0.13)) > 0: # try to kill horizontal scroll when not used, as not to spam shift pins.kbd.press(Keycode.SHIFT) mouse.move(0, 0, round(-y*0.13)) pins.kbd.release(Keycode.SHIFT) else: mouse.move(y, x, 0) self.is_moving = True else: self.is_moving = False
all that to say it is the right code uploaded. I will look to see what I still have of all those tests i did
I assume that you want me to do revision number on the github, looks like the default mouse descriptors is where i gave up so here it is https://github.com/recurvehunt/Circuitpython-keyboard-and-mouse-in-a-single-device-/tree/main/default mouse hid descriptors test/keyboard with default mousee report
I think I see the problem. Your mouse report descriptor in the boot.py is not specifying report id #2. It does not specify any report id.
I will try to get a working version.
OK, I am sending pan values. Here is my code. The boot.py creates a pan mouse. The pan_mouse.py is similar to your mouse2.py. But I made it a free-standing library, so you don't have to put it inside adafruit_hid/. Just put it in CIRCUITPY or CIRCUITPY/lib. I did not write a test program -- I just tested it in the REPL. I tried horizontal scrolling in a browser window with a horizontal scroll bar, and it didn't seem to do anything, but I know it is sending horizontal scroll events. Here are the files, and I'll show the tests after that.
>>> from pan_mouse import PanMouse
>>> import usb_hid
>>> pm = PanMouse(usb_hid.devices)
>>> pm.move(100,100)
>>> pm.move(100,100)
>>> pm.move(100,100,0, 100)
>>> import time
>>> time.sleep(5); pm.move(50,50,0, 100)
>>> time.sleep(5); pm.move(50,50,0, -100)
>>> time.sleep(5); pm.move(50,50,0, -100)
>>> pm.move(50,50,0, -100)
>>> pm.move(50,50,0, 100)
The time.sleep(5) was to give me time to move the mouse into the browser window. Probably I should click inside there. Let me try that. ... hmm, still not working, but I know the panning is being sent. I used sudo evtest in Linux to see the input events. For the last two lines above, notice the REL_HWEEL and REL_HWHEEL_HI_RES values printed by evtest below:
Event: time 1670987044.569871, -------------- SYN_REPORT ------------
Event: time 1670987051.777731, type 2 (EV_REL), code 0 (REL_X), value 50
Event: time 1670987051.777731, type 2 (EV_REL), code 1 (REL_Y), value 50
Event: time 1670987051.777731, type 2 (EV_REL), code 6 (REL_HWHEEL), value -100
Event: time 1670987051.777731, type 2 (EV_REL), code 12 (REL_HWHEEL_HI_RES), value -12000
Event: time 1670987051.777731, -------------- SYN_REPORT ------------
Event: time 1670987058.985790, type 2 (EV_REL), code 0 (REL_X), value 50
Event: time 1670987058.985790, type 2 (EV_REL), code 1 (REL_Y), value 50
Event: time 1670987058.985790, type 2 (EV_REL), code 6 (REL_HWHEEL), value 100
Event: time 1670987058.985790, type 2 (EV_REL), code 12 (REL_HWHEEL_HI_RES), value 12000
Anyway, I think you can use what I started with, and see how it works for you.
Okay thanks for that. I will try to implement and see if it works for me
I just dumped that code into my mouse, and it is indeed horizontally scrolling!
fantastic! I hope you are on your way now.