Confused by the report ID when using HIDAPI through USB - usb

I am a USB HID newbie and I am trying to use the HIDAPI for my application.
I have a question about using HIDAPI (in Visual Studio) regarding the report ID.
When I try to use the HIDAPI and connect to the Microchip Custom Demo,
I am confused about this aspect: The 65-byte report does not make sense to me!
Even if I don't want to set a report ID, I need to set the first byte to 0 and send the 65-byte buffer to the device, but I only receive 64 bytes of data from the Microchip device (because the report is 64 bytes long).
It looks like:
**Host** **Device**
*write_hid*
65 byte --------------->
*read_hid*
<------------------ 64byte
However, it seems weird to me.
Isn't the report that is sent or received always 64 bytes? Because the specifications say the report should have a 64-byte maximum and be sent every 1 ms.
If the answer is yes, why does the API maintain 65 bytes for 1-byte report ID?
Is the report ID contained in the 64 bytes?
The 65-byte data length does not make sense to me.

If your application does not include a Report ID in the HID descriptor, then there shouldn't be a Report ID prepended.
As you can see in the documentation of hid_write, HIDAPI should only send 64-bytes if the first byte is 0 (i.e. there is no Report ID):
unsigned char data[65];
buf[0] = 0; /* Single report */
// Fill report starting at buf[1]
hid_write(device, data, sizeof(data));
When looking at the source code for the libusb implementation, you can see that the Report ID is correctly stripped. On Windows however, the data is passed straight to Windows. I don't know Windows programming, but perhaps this makes a difference. Try testing this on Linux instead.

Related

What is the write SPI command for MX25R device

I want to Write data to this device and read from it.using the manual shown below.
For writing At first I though I should do those two commands:
1st command {0x06};//write enable command
2nd command {0x01,0x2F,0xEF,0xD8}; //write status register based on the table below
But then I saw The PP command which from Fig. 30 shown below which starts with 0x02.
So I assume that in order to store data on this device I need to add 0x02 to my sequence as following send MSB first )
1st command {0x06};//write enable command
2nd command {0x02,0x01,0x2F,0xEF,0xD8} // PP sequence and Write STATUS register the data 0x2F,0xEF,0xD8.
Have I assembled the sequence correctly for this command?
Thanks.
https://www.macronix.com/Lists/Datasheet/Attachments/7461/MX25R8035F,%20Wide%20Range,%208Mb,%20v1.6.pdf
Page programming (PP command 0x02) is not the same as Write Status Register (WRSR command 0x01), so no clearly you don't prepend the sequence with 0x02, since it will then be a PP command and will write data to the device's flash memory, rather the the status register.
WRSR timing diagram is Fig. 15 of the data sheet you linked. PP has no relevance here if WRSR is what you want to do. Conversely if you want to program the flash memory, that is not what WRSR does.
The device has registers for controlling its operation and checking its status, and it has flash memory for storing data - and different commands for accessing these.
Your sequence: 0x02,0x01,0x2F,0xEF,0xD8 will write a single byte 0xD8 to address 0x012FEF. The data sheet says that the LSB of the address should be zero, but does explain what happens when that is not the case, so it is well defined if ill-advised and unlikly to be what you intended. But thereagain it seems likley that writing 0x2FEFD8 to the Status Register was also not what you intended.
The datasheet does have some language issues to hinder you perhaps. For example the PP section uses the word "effort" where I think it intended "effect".

Reading PLC register using ModBusTCPCom in .Net results in address not found

I have to update an old WinForms application. The application uses the AdvancedHMI .NET software.
I am connecting to the PLC (AutomationDirect DirectLogic 06 Series) with no issues, and various other registers are being read accurately.
I am expecting to get a 4 digit value from the register.
I am reading it like so:
Dim rawValue As String = BeltSpeedModbusTcpCom.Read("V3103")
When I read the register I get address not found.
The ladderlogic diagram I am was given is:
I have tried adjusting the address, using 03103, F3103, and other combinations. We can view the address values in real time in the PLC using software the customer has.
According to Page 4-13 of the DL-06 manual, the ā€œVā€ register number is Octal. Try reading ā€œ1603ā€, which is octal 3103 converted to decimal.

hidapi Windows 8.1 hid_write fail

hw : lpc1549 eval board with usb hid test firmware ...
endpoint size 64 bytes
endpoint intr reads out-report buf and displays len and data in hex ...
copies out_report into in_report buf and echoes back with write funct and len
host :
using qt5 , libusb-1.0.19 wingw32 dll and hidapi code
hid test code issues all your api calls (except write and read) sucessfully in linux, win7 and win8.1
test code issues hid_write followed by hid_read and get's data back properly in linux
i am not using the, by hidapi hid_write mandatory flagged Report ID, since the nxp firmware and keil software do not use it (as far as i could figure out) ...
my linux sw sends and receives a defined 64 byte pattern or smaller len) correctly and byte [0] is part of this pattern ... out and in byte [0] data is intentionally different and correct received
running the keil hid client under windows succeeds to properly communicate with the lpc1549 firmware, even they only transfer and echo one byte ...
my firmware has the endpoint size changed to 64 bytes (i hope my changes are correct) and the keil hid client works with it in windows so my assumption is that my descriptors are correct ... hopefully
host sw kububtu 14.04
hid_write len = 17, device 17 bytes received, 17 bytes indicated as received ... all seems to work properly
host sw with hidapi in win 8.1
hid_write len = 17 bytes shows up on device with 16 bytes correct and the rest is 0, but the read indicates a received len of 64 ... i issued a write of 17, received 16 correctly, but was indicated as 64 received
also win 8.1 throws a blank system32/cmd prompt window up ... why ???
the same hangs on win7 and only a hid_write len = 0 succeeds ... popping the same cmd prompt ... received len = 64, but no data transferred (as it would make sense with len = 0)
i can not single step or breakpoints since qt debugger get's segment fault upon app loading
also i link in my qt app to the hidapi "windows/hid.c" code and it is now part my code
sorry for my rather complicated description
why is a Report ID mandatory if it's not being used ... it would be a waste of one byte and if uint32_t alignment is required it would be a waste of about 7 % of the 64 bytes data
why does the keil hid client written in c++ msvs work correctly with my fw and hidapi not
would the functioning of the keil hid client indicate that my fw and my descriptors and report len are correct
What would cause an empty cmd prompt popping up?
What could i be doing wrong (a whole hidapi based app is correctly communicating with a complete usb based firmware pgm, not just the described test code)?
after a couple of days a few things got clear
the ReportID seems to be something in windows and on the host side only ... the firmware is not effected on my setup
also what was not to clear initially is that the ReportID is in addition to the max of 64 report bytes
so i create a buffer with 1 + 64 bytes = 65 ... the 1st one is zero since i do not use the ReportID mechanism and the remaining 64 are normally used
the write call data size needs to be therefore 1 + whatever the reportsize is in the usb hid descriptor endpoint side
in linux there is no ReportID on hid what i could see
next : make sure the data length specified in the write call on the host as well on the device match exactly the endpoint size definitions, otherwise no data gets across either direction and your software might hang (wait forever) on the read on the other end
i hope this might help others to get a better pict of the windows end of the hidapi hid_write calls
Alan Ott wrote me the following
http://www.signal11.us/oss/hidapi/hidapi/doxygen/html/group__API.html#gad14ea48e440cf5066df87cc6488493af
There is always a report ID. You must always send a report ID in HIDAPI, but it will not be sent to the device if the report ID is 0.

Arduino + OV7670 - Without FIFO - Reading Snapshot

I know that there is a lot in internet (http://forum.arduino.cc/index.php?topic=159557.0 for example) about OV7670 and I read a lot about it, but seems something is missing.
First of all I took a look into the way how can we read pixel by pixel from the camera to build the rectangular 600 X 480 image, and this was quite easy to understand considering HREF, VSYNCH and PCLOCK described on documentation here: http://www.voti.nl/docs/OV7670.pdf. I understand XCLOCK as an input I need to give to OV7670 as a kind of cycle controller and RESET would be something to reset it.
So at this point I thought that the functionality of such camera would be covered by wiring the following pins:
D0..D7 - for data (pixel) connected to arduino digital pins 0 to 7 as INPUT on arduino board
XCLK - for camera clock connected to arduino digital pin 8 as OUTPUT from arduino board
PCLK - for pixel clock connected to arduino digital pin 9 as INPUT on arduino board
HREF - to define when a line starts / ends connected to arduino digital pin 10 as INPUT on arduino board
VSYCH - to define when a frame starts / ends connected to arduino digital pin 11 as INPUT on arduino board
GRD - groud connected to arduino GRD
3V3 - 3,3 INPUT connected to arduino 3,3v
RESET - connected to arduino RESET
PWDN - connected to arduino GRD
The implementation for such approach from my point of view would be something like:
Code:
for each loop function do
write high to XCLK
if VSYNCH is HIGH
return;
if HREF is LOW
return;
if lastPCLOCK was HIGH and currentPCLOCK is LOW
readPixelFromDataPins();
end for
My readPixelFromDataPins() basically read just the first byte (as I'm just testing if I can even read something from the camera), and it is written as follows:
Code:
byte readPixelFromDataPins() {
byte result = 0;
for (int i = 0; i < 8; i++) {
result = result << 1 | digitalRead(data_p[i]);
}
return result;
}
In order to check if something is being read from the camera I just print it to the Serial 9600, the byte read from data pins as a number. But currently I'm receiving only zero values. The code I'm using to retrieve an image is stored here: https://gist.github.com/franciscospaeth/8503747.
Did somebody that makes OV7670 work with Arduino already figure out what am I doing wrong? I suppose I'm using the XCLOCK wrongly right? What shall I do to get it working?
I searched a lot and I didn't found any SSCCE (http://sscce.org/) for this camera using arduino, if somebody have it please let me know.
This question is present on arduino forum (http://forum.arduino.cc/index.php?topic=211741.0) too.
your idea is not bad but ...
the xclock need to be a clock (in your program is just a transition from 0 to 1 and is freezing there)
you need also to use I2C with SIOC and SIOD for configuring the camera (or you can use the default settings, but I am not sure if is the correct output format for you, 30F/s,VGA, YUV format ....)
your code execution is slower using the serial output in the same loop with reading data
I will recommend you to toggle the xclock pin and to move the pixel print in a if(). Also you will be able to read Data only in a very precise time, if you want to read only one byte, than after a transition from 0 to 1 of HREF you need to wait for a new transition from 0 to 1 of PCLK (you will be able to see only one 0-1 transition of HREF after 784x2 transitions of PCLK, (640 active pixels + 144 dead time for each line) x 2 (for YUV or RGB are 2 bytes received for each pixel) )
Hello I am Mr_Arduino from the arduino forums. Your issue is that you are reading pixels too slow please do not use digital read to do such a thing. Also if you insist on using a separate function just to read a byte make sure the function is being inlined. You can do this by declaring your function as static inline. Also as mentioned above how are you generating the clock. You can generate the XCLK using PWM on the arduino.
I have created a working example here:
https://github.com/ComputerNerd/arduino-camera-tft/blob/master/captureimage.c
Edit: a 3rd party has copied part but not all of the code from the above link into the answer here. However, the link must remain as the code posted below requires additional files from that source to actually work.
Edit 2: Removed irrelevant code. You will need to modify what you do with the data.
void capImg(void){
cli();
uint8_t w,ww;
uint8_t h;
w=160;
h=240;
tft_setXY(0,0);
CS_LOW;
RS_HIGH;
RD_HIGH;
DDRA=0xFF;
//DDRC=0;
#ifdef MT9D111
while (PINE&32){}//wait for low
while (!(PINE&32)){}//wait for high
#else
while (!(PINE&32)){}//wait for high
while (PINE&32){}//wait for low
#endif
while (h--){
ww=w;
while (ww--){
WR_LOW;
while (PINE&16){}//wait for low
PORTA=PINC;
WR_HIGH;
while (!(PINE&16)){}//wait for high
WR_LOW;
while (PINE&16){}//wait for low
PORTA=PINC;
WR_HIGH;
while (!(PINE&16)){}//wait for high
WR_LOW;
while (PINE&16){}//wait for low
PORTA=PINC;
WR_HIGH;
while (!(PINE&16)){}//wait for high
WR_LOW;
while (PINE&16){}//wait for low
PORTA=PINC;
WR_HIGH;
while (!(PINE&16)){}//wait for high
}
}
CS_HIGH;
sei();
}
You can also find it on github.
You can use my instruction: how to retrieve image from ov7670 It contains all the steps you need. There is also instuction to setup FrameGrabber: how to run framegrabber

Publishing a stream using librtmp in C/C++

How to publish a stream using librtmp library?
I read the librtmp man page and for publishing , RTMP_Write() is used.
I am doing like this.
//Code
//Init RTMP code
RTMP *r;
char uri[]="rtmp://localhost:1935/live/desktop";
r= RTMP_Alloc();
RTMP_Init(r);
RTMP_SetupURL(r, (char*)uri);
RTMP_EnableWrite(r);
RTMP_Connect(r, NULL);
RTMP_ConnectStream(r,0);
Then to respond to ping/other messages from server, I am using a thread to respond like following:
//Thread
While (ThreadIsRunning && RTMP_IsConnected(r) && RTMP_ReadPacket(r, &packet))
{
if (RTMPPacket_IsReady(&packet))
{
if (!packet.m_nBodySize)
continue;
RTMP_ClientPacket(r, &packet); //This takes care of handling ping/other messages
RTMPPacket_Free(&packet);
}
}
After this I am stuck at how to use RTMP_Write() to publish a file to Wowza media server?
In my own experience, streaming video data to an RTMP server is actually pretty simple on the librtmp side. The tricky part is to correctly packetize video/audio data and read it at the correct rate.
Assuming you are using FLV video files, as long as you can correctly isolate each tag in the file and send each one using one RTMP_Write call, you don't even need to handle incoming packets.
The tricky part is to understand how FLV files are made.
The official specification is available here: http://www.adobe.com/devnet/f4v.html
First, there's a header, that is made of 9 bytes. This header must not be sent to the server, but only read through in order to make sure the file is really FLV.
Then there is a stream of tags. Each tag has a 11 bytes header that contains the tag type (video/audio/metadata), the body length, and the tag's timestamp, among other things.
The tag header can be described using this structure:
typedef struct __flv_tag {
uint8 type;
uint24_be body_length; /* in bytes, total tag size minus 11 */
uint24_be timestamp; /* milli-seconds */
uint8 timestamp_extended; /* timestamp extension */
uint24_be stream_id; /* reserved, must be "\0\0\0" */
/* body comes next */
} flv_tag;
The body length and timestamp are presented as 24-bit big endian integers, with a supplementary byte to extend the timestamp to 32 bits if necessary (that's approximatively around the 4 hours mark).
Once you have read the tag header, you can read the body itself as you now know its length (body_length).
After that there is a 32-bit big endian integer value that contains the complete length of the tag (11 bytes + body_length).
You must write the tag header + body + previous tag size in one RTMP_Write call (else it won't play).
Also, be careful to send packets at the nominal frame rate of the video, else playback will suffer greatly.
I have written a complete FLV file demuxer as part of my GPL project FLVmeta that you can use as reference.
In fact, RTMP_Write() seems to require that you already have the RTMP packet formed in buf.
RTMPPacket *pkt = &r->m_write;
...
pkt->m_packetType = *buf++;
So, you cannot just push the flv data there - you need to separate it to packets first.
There is a nice function, RTMP_ReadPacket(), but it reads from the network socket.
I have the same problem as you, hope to have a solution soon.
Edit:
There are certain bugs in RTMP_Write(). I've made a patch and now it works. I'm going to publish that.