-
Notifications
You must be signed in to change notification settings - Fork 670
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
Implement asynchronous transfer functions #63
Comments
This is a very old issue, any updates on the state of this feature? |
I would like to help make this happen. Where do we start? |
How familiar are you with pyusb internals? If you are, please create a branch with these changes. Myself, along with others, will review the changes.
|
Ok. Just to check my understanding of what exactly we want to do, the end goal of this would be to implement the asyncio transfers/protocols for USB? For this, I need to
Is that correct? |
Hi, I'm from the future, in the year 2020. I believe I have a compelling use case for this. I have a device here (Agilent 82347A) that needs transfers submitted in a very specific way:
With the available API, the best we can do is:
What can happen in this case is, the device processes the command in step (1), sees no active IN request, and discards the data. When the IN request arrives, there is no data to send back, and the transfer times out. |
Hi @mrnuke, Do you think you can help me with this? You could start by adding the additonal libusb async functions to the I still don't have a complete picture of how that should be exposed on the higher level and backend-agnostic PyUSB layer. Also, @Armavica mentioned implementing Python's asyncio, which might indeed be a good idea. Anyway, that can wait until we have the C FFI ready, and you could probably use it directly in pygpib until we figure out and implement the higher-level APIs. |
I was just looking into calling libusb_submit_transfer on top of pyusb, albeit in a hackier manner. |
HI @jonasmalacofilho , I tried to implement libusb_fill_bulk_transfer() here Do you have any ideas? |
I think the following async example is what I'd like to see:
To that extent, I have tried something like mrnuke@02521a0 Am I on the right path here? |
I've got some code that I'd like to be async. Would be great if pyusb could be used with different event loops (asyncio, trio, curio, anyio, maybe more). Code currently looks like device.write(0x01, msg, timeout)
device.read(0x81, 0xffff, timeout) I haven't looked much into it yet. But I think it should look like this:
Or from a higher level view:
While an operation is blocking/waiting, other stuff can happen. Event loops need some kind of event, e.g. a readable file descriptor. In strace on a recent Linux system, a long running request currently looks like:
I.e. when I understand it correctly, the usb file descriptor is polled and it will become writable (why not readable?!) when the request is finished. I'll have a look at pyusb and libusb so see if those libs can be extended or if it's a pointless endeavour without a rewrite. |
Looks like libusb got the required functions:
There appears to be another python package which already includes the required bindings: https://github.com/karpierz/libusb |
https://github.com/vpelletier/python-libusb1 |
Actually isochronous transfer is asynchronous in nature and the codes for isoc transfer are already inside pyusb libusb-1.0 backend. So indeed the first step is to have the low level async I/O function for the other types of transfer. As for high level API, I am not so sure. |
Reference: #303 is a WIP implementation. |
@mcuee I don't see why this issue needs to be pinned. While we may want to work on this soon, my opinion is that issues should only be pinned for the benefit of users, and we don't have that many of them hitting this limitation. |
Okay, un-pin it. |
Is there any update on this? |
Maybe you want to give PR #303 a try to see if it works for you or not. It is only for the libusb-1.0 backend which is anyway the way to go for async transfer. |
I will! |
It worked perfectly in my test on an M1 Mac. One comment is that I think a better API would be to directly return a future, so the await device.awrite(0x01, msg, timeout)
await device.aread(0x81, 0xffff, timeout) This should be easy to implement by calling As a reference, I think the websockets library has a really good api: https://websockets.readthedocs.io/en/5.0/intro.html#basic-example |
@rickwierenga, thanks for the feedback! And I agree that the API you and joernheissler propose is more ergonomic, barring any unforeseen reason why the extra indirection is really needed. I'll try to review and make any necessary adjustments to #303. (@mcuee please remind me in one month if I still haven't gotten to it). |
Have a reminder from me instead @jonasmalacofilho 😁 I have no skin in this game, but stumbled on this issue while trying to figure out in pyusb had async support. |
Ah, I missed this one and forgot to remind @jonasmalacofilho. |
BTW, I was actutally testing a few async feature enhancement for libusb language bindings recently.
There are also quite some discussions on hidapi async feature and language bindings like NodeJS and Rust. |
Thanks for the reminder, both of you. Unfortunately I was only able to look into #303 for a short while. IIRC, I found some additional issues in how the libusb async API was being used, but I didn't get to point of actually writing the problems down, or how to solve them (otherwise I'd left comments on #303). This issue is still (fairly high) on my to-do list, but it's unlikely I'll get to it for a couple of moths still (at least). |
Implement asynchronous versions of the transfers functions.
The text was updated successfully, but these errors were encountered: