-
Notifications
You must be signed in to change notification settings - Fork 236
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
python port doesn't work in OS X #54
Comments
I'm not familiar with OS X, if you know what the correct path should be let me know and I can fix it. I'm unsure if OS X supports hidraw by default or not either. What version of OS X are you running? From: Sam Halliday [mailto:notifications@github.com] Looks like the python code is expecting to see the Linux /sys/class/hidraw python render.py No psyco. Expect poor performance. Not really... Traceback (most recent call last): File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/gevent/greenlet.py", line 390, in run
File "/Users/samuel/Documents/Projects/emokit/python/emotiv.py", line 234, in setup
File "/Users/samuel/Documents/Projects/emokit/python/emotiv.py", line 331, in setupPosix
File "/Users/samuel/Documents/Projects/emokit/python/emotiv.py", line 250, in getLinuxSetup
OSError: [Errno 2] No such file or directory: '/sys/class/hidraw' <Greenlet at 0x107b09eb0: <bound method Emotiv.setup of <emotiv.Emotiv object at 0x1078073d0>>> failed with OSError — |
OS X Mountain Lion. No idea what the OS X /dev or /sys would be for this. I was able to build and run the C backend (which involves manually compliing the HIDAPI), but it is little use to me other than confirmation that all the hardware is talking. I'm actually keen on porting the driver to Java / Scala, so any help you can give me would be greatly appreciated. The documentation here seems to be a mix of old and new understanding of how the device works. My first step will be getting the raw USB streaming into Java and then I'll look into decrypting and parsing it. |
I'd be willing to give a java port a try as well. I'm kinda busy ATM. I'll see what I can find out about supporting that OS. From: Sam Halliday [mailto:notifications@github.com] OS X Mountain Lion. No idea what the OS X /dev or /sys would be for this. I was able to build the C backend (which involves manually compliing the HIDAPI). I'm actually keen on porting the driver to Java / Scala, so any help you can give me would be greatly appreciated. The documentation here seems to be a mix of old and new understanding of how the device works. My first step will be getting the raw USB streaming into Java and then I'll look into decrypting and parsing it. — |
I installed the PyUSB library, I was expecting the python code to be using that (since it says so in the docs). |
Yeah, that documentation is kinda old. Forgot to remove that part when it got updated. Run this code for me if you will: import usb.core dev = usb.core.find(find_all=True, idVendor=0x21A1) From: Sam Halliday [mailto:notifications@github.com] I installed the PyUSB library, I was expecting the python code to be using that (since it says so in the docs). — |
If you could send me the output of this as well that would be great. import platform platform = platform.system() From: Sam Halliday [mailto:notifications@github.com] I installed the PyUSB library, I was expecting the python code to be using that (since it says so in the docs). — |
and
|
Err, "it works" even if the USB dongle is not plugged in. You sure that code is right? |
OK, printing the
which is an empty array if the dongle is not plugged in. |
I'll work on it for a bit and see if I can get it working for you. From: Sam Halliday [mailto:notifications@github.com] OK, printing the dev shows this [<usb.core.Device object at 0x105036990>] which is an empty array if the dongle is not plugged in. — |
Cool. This is really just so I have a sanity check – my real goal is to write the Java (Scala) driver. It would appear that USB in Java is non-trivial ... |
@bschumacher just to let you know, I've been able to access the device from java using libusb-legacy (i.e. version 0.1.x) through libusb4j. Any advice, beyond what should be obvious from the c / python code, would be greatly appreciated! Would you be interested in getting a pull request for the Java driver? I'm really confused how it would fit into your structure. Maybe I could create a |
Does the usb device object have a valid serial number in it properties? Without having access to a Mac I'm kinda stuck on getting the serial number for the Python version. Store packets/frames in one thread, decrypt them in another. Pick a fast AES library. Sure. Yeah I guess just make a java dir in the root. From: Sam Halliday [mailto:notifications@github.com] @bschumacherhttps://github.com/bschumacher just to let you know, I've been able to access the device from java using libusb-legacy (i.e. version 0.1.x) through libusb4j. Any advice, beyond what should be obvious from the c / python code, would be greatly appreciated! Would you be interested in getting a pull request for the Java driver? I'm really confused how it would fit into your structure. Maybe I could create a java or scala folder and do the usual maven/sbt thang in there. — |
@bschumacher depends what you mean by a valid serial number. My Java code says it is "3". Does that sound right?
|
No, it should be like SNXXXXXXXXGM. From: Sam Halliday [mailto:notifications@github.com] @bschumacherhttps://github.com/bschumacher depends what you mean by a valid serial number. My Java code says it is "3". Does that sound right? usb_device$ByReference(native@0x7fa0e30a6400) (1112 bytes) { usb_device$ByReference next@0=null usb_device$ByReference prev@8=usb_device$ByReference(native@0x7fa0e30a5e00) (1112 bytes) {...} byte filename[1025]@10=[B@4a6774ee usb_bus$ByReference bus@418=usb_bus$ByReference(native@0x7fa0e3000600) (1072 bytes) {...} usb_device_descriptor descriptor@420=usb_device_descriptor(native@0x7fa0e30a6820) (18 bytes) {
} usb_config_descriptor$ByReference config@438=usb_config_descriptor$ByReference(native@0x7fa0e291d6e0) (40 bytes) {...} Pointer dev@440=native@0x7fa0e291d360 byte devnum@448=0 byte num_children@449=0 PointerByReference children@450=null } — |
That's the same thing as the pyusb library was giving me. You can get your serial number from the dmesg output possibly if you have that on a Mac. From: Sam Halliday [mailto:notifications@github.com] @bschumacherhttps://github.com/bschumacher depends what you mean by a valid serial number. My Java code says it is "3". Does that sound right? usb_device$ByReference(native@0x7fa0e30a6400) (1112 bytes) { usb_device$ByReference next@0=null usb_device$ByReference prev@8=usb_device$ByReference(native@0x7fa0e30a5e00) (1112 bytes) {...} byte filename[1025]@10=[B@4a6774ee usb_bus$ByReference bus@418=usb_bus$ByReference(native@0x7fa0e3000600) (1072 bytes) {...} usb_device_descriptor descriptor@420=usb_device_descriptor(native@0x7fa0e30a6820) (18 bytes) {
} usb_config_descriptor$ByReference config@438=usb_config_descriptor$ByReference(native@0x7fa0e291d6e0) (40 bytes) {...} Pointer dev@440=native@0x7fa0e291d360 byte devnum@448=0 byte num_children@449=0 PointerByReference children@450=null } — |
@bschumacher hmm, no I don't seem to have such a dmesg in OS X. I presume I need this to do the decryption? |
@bschumacher got it :-D it is visible from the System Information. I'll just have to do this manually I suppose as it is not trivial to automate. |
Can you access that system information from Python or Java? From: Sam Halliday [mailto:notifications@github.com] @bschumacherhttps://github.com/bschumacher hmm, no I don't seem to have such a dmesg in OS X. I presume I need this to do the decryption? — |
Not that I can see – it's a GUI interface. I tried a |
@bschumacher should I be using "bulk read" for this? If so, what size are the packets and how on earth do I make sure that I don't start somewhere in the middle of a valid datum? |
Read 32bytes at a time, Not sure of the magic behind the hidraw.read() function. I assume the library you're using has a read function with a specified buffer or buffer size. These documents are helpful: https://github.com/bschumacher/emokit-1/blob/master/doc/emotiv_protocol.asciidoc From: Sam Halliday [mailto:notifications@github.com] @bschumacherhttps://github.com/bschumacher should I be using "bulk read" for this? If so, what size are the packets and how on earth do I make sure that I don't start somewhere in the middle of a valid datum? — |
Note that I'm kinda sorta working on maintaining cython-hidapi, which should make this work fine on OS X if someone wants to port it. http://www.github.com/qdot/cython-hidapi I know there's someone else (issue #53 I think?) working on a pyusb version too. |
The library is libusb 0.1 and I've hit a bit of a problem – everytime I call libUSB.usb_bulk_read(handle, 0x80, bytes, 32, 1000); or libUSB.usb_interrupt_read(handle, 0x80, bytes, 32, 1000); I'm getting a core dump. I don't know what the problem is. |
ok, I'm over that now – but with the following code I'm getting just zeros so I'm stuck: (I've sean that 80 is the endpoint for IN, but I don't know what this means) public static void main(String[] args) {
libUSB.usb_init();
libUSB.usb_find_busses();
libUSB.usb_find_devices();
usb_bus bus = libUSB.usb_get_busses();
for (; bus != null; bus = bus.next) {
for (usb_device.ByReference dev = bus.devices; dev != null; dev = dev.next) {
usb_device_descriptor descriptor = dev.descriptor;
if (descriptor.idVendor == 0x21A1) {
usb_dev_handle handle = libUSB.usb_open(dev);
libUSB.usb_claim_interface(handle, 0);
byte[] bytes = new byte[32];
for (int i = 0; i < 10; i++) {
libUSB.usb_interrupt_read(handle, 80, bytes, 32, 500);
System.out.println(Arrays.toString(bytes));
}
libUSB.usb_release_interface(handle, 0);
libUSB.usb_close(handle);
}
}
}
} |
You might want to take a look at http://code.google.com/p/javahidapi/ as libusb 0.1 is years old and unmaintained, and porting USB drivers without knowing with the protocol and platform eccentricies is a really time consuming process (though hey, you'll know more about USB in the end! :) ). That said, your problem there starts with the interface address, which is most definitely not 80. The numbers you need for interface endpoints are at https://github.com/openyou/emokit/blob/master/include/emokit/emokit.h However, since you're trying to use a libusb route versus straight OS X HID calls, you're going to have to shunt the HID layer via a kext or this code will /never/ work. Since kext shunting HID sucks and is violently unreliable, I'm not even going to explain that process and am will stick with recommending checking out javahidapi. :) |
I have no idea what you just said. I still get zeros even if I use 0x02 or 0x82 – is that what you expected? I'll look into javahidapi (which I have looked at and it failed to build) but I'd like to know what you mean by shunt the HID via a kext? Why shouldn't I just be able to get the raw data from the usb device? |
OK, getting javahidapi working now to list all my devices – I can even see my Emotive serial number, so that's a good sign. Looks like I'll have to mess around with installing hidapi on my target platform and also JNI building with this library, which is suboptimal... |
(looks like it might not depend on hidapi afterall, but still a massive maven pain in the ass) |
Welcome to cross language cross platform driver writing, where no process is ever fun. :3 OS X sees the device as a human interface device, and takes it for its own when the OS boots. So you can't access it via raw libusb calls without telling the kernel not to do that, which sucks. HIDAPI does things the right way, actually making the necessary calls to talk to the kernel the way it expects. Hence me recommending HIDAPI. Oh, and going WAY back up: hidapi is only linux. Not OS X, not BSD. Just linux. The python code started as a proof of concept, though I just brought in a new patch to make it work better. However I haven't tested that at all, mainly relying on the kindness of pull requests there. |
the hidapi library http://www.signal11.us/oss/hidapi/ does seem to build for OS X now. This is what I used to get your C binary to build and confirm that my hardware works :-) Thansk for the description about HID and OS X – I wish I'd learnt that about 5 hours ago. |
Hmm, I can't see where to pass the endpoint info to javahidapi – so the demo just blocks on |
Notice the C code doesn't actually use the endpoint? You only needed that if you were gonna go libusb. HIDAPI figures that out for you. You should be able to straight translate the C to java. |
the java hdiapi seems to extract the name and serial OK, but the "feature report" is coming out all zeroes. That's not a good sign. |
ok, by magic it's now coming out as:
.... bah! the numbers seme to be random. The only thing that stays the same is that 8 bytes are written. |
Perhaps the HID API strips the first entry (which is the report number anyway) when it returns. That would mean I am sometimes getting all zeros (which is clearly bad) or
instead of the expected
(byte is signed in Java, remember) Even if I Completely stuck. |
w00t! I'm getting some numbers coming in the stream. The report is still coming out as Is this report a bad sign? I definitely bought the consumer Emotive. |
I believe the feature report is only used to detect wether or not you have a research headset. If you know your headset is a consumer grade just use the consumer grade encryption key and come back to that part later. From: Sam Halliday [mailto:notifications@github.com] w00t! I'm getting some numbers coming in the stream. The report is still coming out as [33, -1, 31, -1, 30, 0, 0, 0, 0] but it's reading. It's rather sporadic as it only happens every few times I run the javahid demo, other times it just blocks forever. Is this report a bad sign? I definitely bought the consumer Emotive. — |
@bschumacher according to the C code, I have a research grade one then (although I've not debugged the C code to see what it is finding – there may well be a bug in the javahdiapi). It's a bit concerning that it sometimes comes out as all zeros, and worse yet that it hangs indefinitely. |
For the consumer grade value is supposed to be 0, so if you're getting that from the feature report that is probably ok. The product name of one of the two device that are detected is also all 0s, which is the one you need to open. From: Sam Halliday [mailto:notifications@github.com] @bschumacherhttps://github.com/bschumacher according to the C code, I have a research grade one then (although I've not debugged the C code to see what it is finding – there may well be a bug in the javahdiapi). It's a bit concerning that it sometimes comes out as all zeros, and worse yet that it hangs indefinitely. — |
@bschumacher hmm, so there are two USB devices? I'll have to work out how to distinguish between them. I'm actually seeing the opposite – when the report comes back all zeroes, then the read blocks forever. I think the reason I wasn't getting any signal earlier on today (with javahidapi) was because I had tried so many different libraries to access the usb device that it probably shut down. When I unplugged it and put it back in again, I started to get a stream (some of the time). |
Yeah the product names differ, at least there are on Windows and Linux boxes. On windows I have my code open both devices, I guess I could do the same with the linux ones also. Have you tried the cython-hidapi yet? I know your working on the Java version, I'm just curios if it works on OS X. From: Sam Halliday [mailto:notifications@github.com] @bschumacherhttps://github.com/bschumacher hmm, so there are two USB devices? I'll have to work out how to distinguish between them. I'm actually seeing the opposite – when the report comes back all zeroes, then the read blocks forever. I think the reason I wasn't getting any signal earlier on today (with javahidapi) was because I had tried so many different libraries to access the usb device that it probably shut down. When I unplugged it and put it back in again, I started to get a stream (some of the time). — |
I'll have a look at cython once I've done the Java port, if that helps out your development. |
@bschumacher yeah, that's what it was! Two devices with identical product numbers
|
So when your code hangs, it's probably because the interface you had open wasn't receiving any frames from the headset. The one with all 0s in the report is the one you want. @bschumacherhttps://github.com/bschumacher yeah, that's what it was! Two devices with identical product numbers HIDDeviceInfo [path=USB_21a1_0001_0x7f9411a48d30, vendor_id=8609, product_id=1, serial_number=SN201211150768GM, release_number=3, manufacturer_string=Emotiv Systems Inc., product_string=EPOC BCI, usage_page=65535, usage=2, interface_number=-1] REPORT = [33, -1, 31, -1, 30, 0, 0, 0] HIDDeviceInfo [path=USB_21a1_0001_0x7f9411a49390, vendor_id=8609, product_id=1, serial_number=SN201211150768GM, release_number=3, manufacturer_string=Emotiv Systems Inc., product_string=EPOC BCI, usage_page=61695, usage=16, interface_number=-1] REPORT = [0, 0, 0, 0, 0, 0, 0, 0] — |
@bschumacher interesting, I thought the one I wanted was the one that wasn't all zeros. Let's move the Java talk to the pull request at #55 This thread hasn't been about Python in a long time :-D (btw, did you know that your email comments are quoting the original messages on github? I thought github cleaned that up) |
Hello - I'm sorry to reopen this thread, but I'm having the same problem as this thread was started on, but can't fix it with the above. I installed PyUSB and ran the code you posted above: import usb.core Instead of "It Works!" I get: Traceback (most recent call last): When I run python interactively and try "dev = usb.core.find(find_all=True, idVendor=0x21A1)" I get the error: dev = usb.core.find(find_all=True, idVendor=0x21A1) I'm guessing that python is having trouble finding the dongle? Do you have any advice or could you help me solve this problem? I'm trying to get Emokit working on my Mac before trying to install it on a RaspberryPi. Thanks. |
Update - and found another post which said to set After doing this, when I do Does this mean that it's not finding the dongle? |
Well, it took a very long time but this is working now. Install HIDAPI and cython-hidapi. |
Sweet, thanks @bschumacher. |
Btw, that note about cython-hidapi hasn't made it into any README yet. |
Oops, I overlooked that file. Its ready to be pulled in. |
Merged that. |
Looks like the python code is expecting to see the Linux
/sys/class/hidraw
The text was updated successfully, but these errors were encountered: