>>Assuming there are no other bugs in the libusbxhid library, for writing data >>you have to guess the reportType (in, out, feature) and reportNum parameter >>and set the report data buffer correctly (first byte is the report number) >>for your device. Have a look at similar devices.
I don't know if there is a bug or not... but I "Think" I have the information I need. I found this device documented here: https://github.com/rubienr/machinekit/tree/feature-xhc-whb04b-6/src/hal/user_comps/xhc-whb04b-6 it states: "Data transmitted is packed as 7 bytes plus a constant leading byte 0x06 which is the report ID. The data exclusive report ID reads as follows:" this matches the python code I was trying to duplicate... so I send a $06 then 7 bytes of data at a time. It also describes the data structure as well. The C code at https://github.com/rubienr/machinekit/blob/feature-xhc-whb04b-6/src/hal/user_comps/xhc-whb04b-6/usb.cc Uses libusb... here is the relevant section: It's in C but it's commented pretty well.. and describes the exact parameters passed to libusb_control_transfer void Usb::sendDisplayData() { outputPackageBuffer.asBlocks.init(&outputPackageData); if (mIsSimulationMode) { *verboseTxOut << "out 0x" << outputPackageBuffer.asBlocks << endl << std::dec << "out size " << sizeof(outputPackageBuffer.asBlockArray) << "B " << outputPackageData << endl; } for (size_t idx = 0; idx < (sizeof(outputPackageBuffer.asBlockArray) / sizeof(UsbOutPackageBlockFields)); idx++) { UsbOutPackageBlock& block = outputPackageBuffer.asBlockArray[idx]; size_t blockSize = sizeof(UsbOutPackageBlock); // see also // http://www.beyondlogic.org/usbnutshell/usb6.shtml // http://libusb.sourceforge.net/api-1.0/group__desc.html // http://libusb.sourceforge.net/api-1.0/group__misc.html int r = libusb_control_transfer(deviceHandle, // send to hid descriptor: bmRequestType == LIBUSB_DT_HID == 0x21 == (interface | endpoint) LIBUSB_DT_HID, // bRequest == LIBUSB_REQUEST_SET_CONFIGURATION == 0x09 == set configuration LIBUSB_REQUEST_SET_CONFIGURATION, // wValue: if bRequest == LIBUSB_REQUEST_SET_CONFIGURATION the configuration value 0x0306, // wIndex, device interface number 0x00, // data to transmit block.asBuffer.asBytes, // wLength, data length blockSize, // transfer timeout[ms] 0); if (r < 0) { std::cerr << "transmission failed, try to reconnect ..." << endl; setDoReconnect(true); return; } } } So I tried with libusbxhid: libusbhid_set_report(device_context, HID_REPORT_TYPE_FEATURE, $6 , 8 , WhB04_Packet ) and I get control transfer to usb device failed! so inside function libusbhid_set_report, I put a bunch of writelns to show what is being passed to libusb_control_transfer: Writeln('device handle ='); Writeln('bmRequestType = $', inttohex(LIBUSB_CONTROL_REQUEST_TYPE_OUT,4)); Writeln('bRequest = $', inttohex(HID_SET_REPORT,4) ); Writeln('wValue = $', inttohex((reportType << 8) or reportNum,4) ); Writeln('wIndex = $', 0 ); Writeln('data = ', '$'+Inttohex(report_data[0],2),' $'+Inttohex(report_data[1],2),' $'+Inttohex(report_data[2],2),' $'+Inttohex(report_data[3],2),' $'+Inttohex(report_data[4],2),' $'+Inttohex(report_data[5],2), ' $'+Inttohex(report_data[6],2),' $'+Inttohex(report_data[7],2)); Writeln('wLength = $', Inttohex(reportLen,2) ); Writeln('timeout = $', 0 ); Result:=libusb_control_transfer(hid_device_context.usb_device_handle,LIBUSB_CONTROL_REQUEST_TYPE_OUT{????},HID_SET_REPORT,(reportType << 8) or reportNum, 0{interface_num}, @report_data, reportLen{sizeof(data)},0{no timeout}); Suspend 06 FD FE FF 01 02 03 04 device handle = bmRequestType = $0021 bRequest = $0009 wValue = $0306 wIndex = $0 data = $06 $FD $FE $FF $01 $02 $03 $04 wLength = $08 timeout = $0 control transfer to usb device failed! -1 It shows I'm getting the same values for everything.... but yet it's still failing. I have this attempt on my fork at https://github.com/Zaaphod/libusbxhid I'm not sure it's libusbxhid though.. because I also can't get it to work with pas-libusb I can run test3controlasync.pas with my device and it does send a request to the device and retrieves some information from it... so I modified that program (test3controlasync_2.pas) to just pass the same paramaters as above and then it doesn't work anymore... here's the output from test3controlasync_2.pas Running "i:\programming\pas-libusb_test_dll\src\examples\test3controlasync_2.exe " Submitting control transfer Finished Transfer, Data = 38, Status = 0, ActualLength = 18 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor $10CE idProduct $EB93 bcdDevice 1.00 iManufacturer 1 iProduct 0 iSerialNumber 0 bNumConfigurations 1 Done. CT.bmRequestType = 21 CT.bRequest = 09 CT.wValue = 306 CT.wIndex = 00 CT.wLength = 07 CT.Timeout = 00 Submitting control transfer USB Error: Submit: LIBUSB_ERROR_IO: LIBUSB_ERROR_IO So it worked for the first information request (the default one including with the original test2controlasync.pas) , but not for my attempted request.. this leads me to believe that I have something wrong and it's not a bug... but I'm lost as to what it might be.. my attempt is on my fork here: https://github.com/Zaaphod/pas-libusb/blob/Hack/src/examples/test3controlasync_2.pas >> One thing I'm really not sure how to handle with threads is this.... ok so >> I have my main fast read thread going in the tightest loop possible... but >> now I want to write something to the display (assuming I ever figure that >> out and don't just put a sticker over the display and look at the screen >> instead :D ) It seems I would have to stop reading to get a chance to >> write something.. I did a little test and I can do a suspend(Thread_ID) >> and resume(Thread_ID) but what if it's in the middle of a read.. but only >> got 6 of the 8 bytes when I do the suspend?? Now I am not really ready to >> write..... so what method can I use to do a >> suspend_thread_just_before_the_next_read_happens() ? so that when the >> thread is suspended, the read is completed and the buffer updated.. etc.. >> and the USB system and libusb are all ready for me to send my write >> commands? Resuming would be no problem.. because it was suspended at the >> correct position.. I can just resume when I am done with the write and >> everything should be fine. >My guess is that it would be better to leave the time sensitive read >thread to do the fast reads and immediate calculations and leave writing >to the device screen in a separate thread (even main thread), with a >lower update frequency! Yes, that was what I was attempting to describe.. but I can't write to the usb device if the read thread happens to be in the middle of a read... so how do I pause the read thread at the correct time so it's not partially in the middle of reading a packet, and I can't read again until I'm done writing. I figure I can just check for some period of time of idle handwheel input before I stop the read thread and do the write then start the read thread again, because only the handwheel produces such a large stream of data.. but still I’m not sure how to make sure I stop it at the correct time. James _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal