I am working in libusb and have minimal knowledge on C++. I am trying to understand the API of libusb and write code accordingly. But I am unable to understand how to declare and use variables as variable or pointer or double or triple pointer.
The below code is from question. How to find what level of pointers to be used while declaring these variables from the API documentation. Is there any documentation or tutorial videos that explains these things.
libusb_context *context = NULL ;
libusb_device_handle *dev_handle = NULL ;
libusb_device **devs ;
int rc = 0 ;
ssize_t count ; //holding number of devices in list
For example, consider libusb_device_handle. How to declare this and use it?
typedef struct libusb_device_handle libusb_device_handle
The syntax of libusb_strerror() is const char * libusb_strerror (int errcode). The function returns constant string. Should I declare a char or char array or string to read the returned value. If the below way of usage right?
char char *err_code;//declaration
err_code = libusb_strerror(rc);
if the returned value is a string, then how can a characer pointer hold it?
An example would be really helpful.
3)Here is my entire code. I can open the device. But the bulk transfer command returns 5 and fails. I am not sure at which part I am making mistake.
#include <iostream>
#include "libusb.h"
#define IN_EP 0x81
#define OUT_EP 0x02
int main(){
libusb_context *context = NULL;
libusb_device_handle *dev_handle = NULL ;
libusb_device **devs ;
int rc = 100 ;
//ssize_t count ; //holding number of devices in list
unsigned int vid=0x1234;
unsigned int pid=0x5678;
unsigned char data[10];
data[0]=128;
int transferred = 0;
unsigned int timeout = 5000;
//std::string str[100];
const char* err_code;
rc = libusb_set_option(context, LIBUSB_OPTION_LOG_LEVEL,2);
if (rc==0){ std::cout<<"libusb_setOption worked:"<<rc<<"\n"; }
else{ std::cout<<"libusb_setOption_Failed:"<<rc<<"\n"; }
rc = libusb_init(&context);
if (rc==0){ std::cout<<"libusb_init worked:"<<rc<<"\n"; }
else{ std::cout<<"libusb_init Failed"<<rc<<"\n"; }
dev_handle = libusb_open_device_with_vid_pid(context,vid,pid);
if (dev_handle == NULL){
std::cout<<"libusb_open Failed"<<"\n";
libusb_exit(context);std::cout<<"libusb_exit"<<"\n";exit(1); }
else{ std::cout<<"libusb_opened"<<"\n"; }
rc = libusb_bulk_transfer(dev_handle,OUT_EP,data,1,&transferred, timeout); //Send data to device
if (rc==0){ std::cout<<"libusb_write worked:"<<rc<<"; Wrote "<<transferred<<" bytes\n"; }
else{ std::cout<<"libusb__Write failed"<<rc<<"; Wrote "<<transferred<<" bytes\n"; }
err_code = libusb_strerror(rc);
rc = libusb_bulk_transfer(dev_handle,IN_EP,data,3,&transferred, timeout); //Read data from device
if (rc==0){ std::cout<<"libusb_read worked:"<<rc<<" ; Read"<<transferred<<" bytes; Data:"<<data<<"\n";
std::cout<<data[0]<<" "<<data[1]<<" "<<data[2]<<"\n"; }
else{ std::cout<<"libusb__read failed"<<rc<<"; Read "<<transferred<<" bytes\n"; }
libusb_close(dev_handle);
std::cout<<"libusb_close"<<"\n";
libusb_exit(context);
std::cout<<"libusb_close"<<"\n";
return 0;
}
Any help will be appreciated.
[...] For example, consider libusb_device_handle. How to declare this and use it?
You declare it exactly like in your code:
libusb_device_handle *dev_handle = NULL;
Because libusb_open_device_with_vid_pid() returns a pointer to libusb_device_handle, your dev_handle must also be a pointer to that.
You might be confused because of devs being a pointer-to-pointer. This is because it is actually returning a pointer to an array, but since you are not even using that in your code, I would forget about it for now.
The syntax of libusb_strerror() is const char * libusb_strerror (int errcode). The function returns constant string. Should I declare a char or char array or string to read the returned value?
You should declare a variable exactly the same as the return type of libusb_strerror(), thus:
const char *err_string;
err_string = libusb_strerror(rc);
If the returned value is a string, then how can a characer pointer hold it?
The returned value is a pointer, you just make a copy of the pointer. The pointer points to some part of memory where the string is stored. You don't have to worry about how libusb allocated it.
I can open the device. But the bulk transfer command returns 5 and fails. I am not sure at which part I am making mistake.
The code looks mostly fine, except you want to call libusb_strerror() after the second call to libusb_bulk_transfer(), not right before it. Error code -5 is LIBUSB_ERROR_NOT_FOUND. This might mean it didn't find the endpoint. Are you sure IN_EP and OUT_EP are set correctly?
Related
I've found a very strange issue with both printf (and printf_s), and also std::cout. I'm not sure if it's some short of "glitch" or error in these functions, or if I'm doing something wrong. Since both functions do the same, I'm assuming I'm not doing it the right way.
I have the following structures in my program (By the way, this is a Visual C++ 2010 project):
#pragma pack(push, 1)
typedef struct nameentry
{
char NAME[17];
char EXT[4];
}NAMEENTRY;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct fileentry
{
unsigned int ID;
NAMEENTRY FILENAME;
unsigned int GPFID;
unsigned long long int FPOINTER;
size_t FILESIZE;
}FILEENTRY;
#pragma pack(pop)
Now I have the following portion of code:
NAMEENTRY fname = MCreateNameEntry("LONGFILE.JPG");
FILEENTRY* myfile_ = SearchFileByPkgID(0, fname);
printf("%s", myfile_->FILENAME.NAME);
So what this code is supposed to do is, create an instance of NAMEENTRY with NAME=LONGFILE, and EXT=JPG. Both character arrays are null terminated (last byte is a 0). Then create an instance of FILEENTRY with it's corresponding data from a database I'm developing, then print the name of the file from the FILEENTRY's NAMEENTRY structure.
After running the code, what I get instead of the name of the file, is... garbage. The classic garbage you get when trying to print text from a bad pointer. If I try to print any of the other fields, I also get wrong values.
So obviously, my first thought was that one of my functions were not returning the right value. So I started inspecting the code and, to my surprise, they are actually returning the right values and the structure is filled with the right data. I get the proper values in each field, every character array ends with a 0, etc.
So then I said... "What if I copy the entire block into another instance of FILEENTRY?", and I tried this:
NAMEENTRY fname = MCreateNameEntry("LONGFILE.JPG");
FILEENTRY* myfile_ = SearchFileByPkgID(0, fname);
FILEENTRY dMem;
memcpy(&dMem, myfile_, sizeof(FILEENTRY));
printf("%s", dMem.FILENAME.NAME);
And guess what? It works perfectly fine. I get the name of the file, no garbage. So I'm assuming, either the problem is inside of printf (I also tried std::cout with the same results), or I am doing something wrong when using these functions.
Well, that helps. Seems like the problem was trying to return a pointer to a local variable, as Igor Tandetnik suggested.
So as a workaround, I'm not sure if this is a proper way of handling this, instead of define a local variable, I'm using calloc to allocate a memory block for a FILEENTRY pointer, then fill it and return it. And yes, it seems to work this way.
This is the actual code of the function:
FILEENTRY* SearchFileByPkgID(int ID, NAMEENTRY fname)
{
FILEENTRY* myFile = (FILEENTRY*)calloc(sizeof(FILEENTRY),1);
std::vector<int> results;
unsigned int* dptable = GetDPTableByPkgId(ID);
bool found = false;
for(int x = 0; x < 1024; x++)
{
if(dptable[x] > 0)
{
fseek(PDBFILE, dptable[x], SEEK_SET);
fread(myFile, sizeof(FILEENTRY), 1, PDBFILE);
if(strcmp(myFile->FILENAME.EXT, fname.EXT) == 0)
if(myFile->FILENAME.NAME[0] == fname.NAME[0])
results.push_back(dptable[x]);
}
}
for(int y = 0; y < results.size(); y++)
{
fseek(PDBFILE, results[y], SEEK_SET);
fread(myFile, sizeof(FILEENTRY), 1, PDBFILE);
if(strcmp(myFile->FILENAME.NAME, fname.NAME) == 0)
{
found = true;
break;
}
}
results.clear();
if(found)
return myFile;
else
return 0L;
}
Any more suggestions are wellcome.
I created a function that returns an error code (ErrCode enum) and pass two output parameters. But when I print the result of the function, I don't get the correct values in the array.
// .. some codes here ..
ErrCode err;
short lstCnt;
short lstArr[] = {};
err = getTrimmedList(lstArr, &lstCnt);
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d", i, lstArr[i]);
// .. some codes here ..
The getTrimmedList function is like this:
ErrCode getTrimmedList(short* vList, short* vCnt)
{
short cnt;
ErrCode err = foo.getListCount(FOO_TYPE_1, &cnt);
if (NoError!=err) return err;
short* list = new short [cnt];
short total = 0;
for (short i=0; i<cnt; ++i)
{
FooBar bar = foo.getEntryByIndex(FOO_TYPE_1, i);
if (bar.isDeleted) continue;
list[total] = i;
++total;
}
*vCnt = total;
//vList = (short*)realloc(index, sizeof(short)*total);
vList = (short*)malloc(sizeof(short)*total);
memcpy(vList, list, sizeof(short)*total)
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d", i, lstArr[i]);
return NoError;
}
where:
foo is an object that holds arrays of FooBar objects
foo.getListCount() returns the number of objects with type FOO_TYPE_1
FOO_TYPE_1 is the type of object we want to take/list
foo.getEntryByIndex() returns the ith FooBar object with type FOO_TYPE_1
bar.isDeleted is a flag that tells if bar is considered as 'deleted' or not
What's my error?
Edit:
Sorry, I copied a wrong line. I commented it above and put the correct line.
Edit 2
I don't have control over the returns of foo and bar. All their function returns are ErrCode and the outputs are passed through parameter.
Couple of questions before I can answer your post...
Where is "index" defined in:
vList = (short*)realloc(index, sizeof(short)*total);
Are you leaking the memory associated with:
short* list = new short [cnt];
Is it possible you have accidentally confused your pointers in memory allocation? In any case, here is an example to go from. You have a whole host of problems, but you should be able to use this as a guide to answer this question as it was originally asked.
WORKING EXAMPLE:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int getTrimmedList(short** vList, short* vCnt);
int main ()
{
// .. some codes here ..
int err;
short lstCnt;
short *lstArr = NULL;
err = getTrimmedList(&lstArr, &lstCnt);
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d\n", i, lstArr[i]);
// .. some codes here ..
return 0;
}
int getTrimmedList(short** vList, short* vCnt)
{
short cnt = 5;
short* list = new short [cnt];
short* newList = NULL;
short total = 0;
list[0] = 0;
list[1] = 3;
list[2] = 4;
list[3] = 6;
total = 4;
*vCnt = total;
newList = (short*)realloc(*vList, sizeof(short)*total);
if ( newList ) {
memcpy(newList, list, sizeof(short)*total);
*vList = newList;
} else {
memcpy(*vList, list, sizeof(short)*total);
}
delete list;
return 0;
}
You have serious problems.
For starters, your function has only one output param as you use it: vCnt.
vList you use as just a local variable.
realloc is called with some index that we kow nothing about, not likely good. It must be something got from malloc() or realloc().
The allocated memory in vList is leaked as soon as you exit getTrimmedList.
Where you call the function you pass the local lstArr array as first argument that is not used for anything. Then print the original, unchanged array, to bounds in cnt, while it has 0 size still -- behavior is undefined.
Even if you managed to pass that array by ref, you could not reassign it to a different value -- C-style arrays can't do that.
You better use std::vector that you can actually pass by reference and fill in the called function. eliminating the redundant size and importantly the mess with memory handling.
You should use std::vector instead of raw c-style arrays, and pass-by-reference using "&" instead of "*" here. Right now, you are not properly setting your out parameter (a pointer to an array would look like "short **arr_ptr" not "short *arr_ptr", if you want to be return a new array to your caller -- this API is highly error-prone, however, as you're finding out.)
Your getTrimmedList function, therefore, should have this signature:
ErrCode getTrimmedList(std::vector<short> &lst);
Now you no longer require your "count" parameters, as well -- C++'s standard containers all have ways of querying the size of their contents.
C++11 also lets you be more specific about space requirements for ints, so if you're looking for a 16-bit "short", you probably want int16_t.
ErrCode getTrimmedList(std::vector<int16_t> &lst);
It may also be reasonable to avoid requiring your caller to create the "out" array, since we're using smarter containers here:
std::vector<int16_t> getTrimmedList(); // not a reference in the return here
In this style, we would likely manage errors using exceptions rather than return-codes, however, so other things about your interface would evolve, as well, most likely.
Sorry, I cant use separate class for this and I tried to build following code and getting same output when calling from out side in loop.
unsigned int crypt_rand()
{
HCRYPTPROV hProvider = 0;
const DWORD dwLength = sizeof(unsigned int);
unsigned int pbBuffer[dwLength] = {};
if (!::CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return 1;
if (!::CryptGenRandom(hProvider, sizeof(unsigned int), reinterpret_cast<PBYTE>(&pbBuffer)))
{
::CryptReleaseContext(hProvider, 0);
return 1;
}
if (!::CryptReleaseContext(hProvider, 0))
return 1;
return (unsigned int)pbBuffer;
}
If I am calling this function from loop getting same output every time.Is it anything I can give like input as time in this method.Can you plz help me on this?
for (DWORD i = 0; i < 5; ++i)
{
rand_no = crypt_rand();
std::cout << "windows::"<<i<<"::"<<rand_no<< std::endl;
}
Output is
windows::0::4519964
windows::1::4519964
windows::2::4519964
windows::3::4519964
windows::4::4519964
The use of casts (the reinterpret_cast and the one in the return statement) is hiding some important compiler errors that would have allowed you to write this code correctly in the first place.
Avoid the casts as much as you can, fix the types instead.
CryptGenRandom expects a
BYTE *pbBuffer
parameter. Pass it a pointer to an array of BYTE not anything else (you are passing a pointer to an array of int).
In your return statement you are casting an address to unsigned int. You need to take the BYTE array and convert the values it contains to an int (you can find examples of that online or you can make one yourself via sit shifts and additions). What you are doing now is probably outputting the same address (or part of it) over and over again.
To clarify, define your array as
BYTE pbBuffer[dwLength] = {};
and call your function as
::CryptGenRandom(hProvider, dwLength, pbBuffer)
Avoid casts, especially the C style casts, and read about arrays. In C++, when passed to a function an array decays to a pointer to the first element of the array. If you have an array of BYTE it will decay to a BYTE*, the expected type of your function.
The problem is in return (unsigned int)pbBuffer; here you are just getting address of pbBUffer everytime.If pbBuffer is an array and function crypt_rand is returning unsigned int then it should be elements of array at return.
You need to enable warnings during your compilation.These kind of possible errors must be there as warning.
You want a random number that is an unsigned int?
Just cast the contents of the BYTE buffer to an unsigned int
How about:
unsigned int crypt_rand()
{
HCRYPTPROV hProvider = 0;
const DWORD dwLength = sizeof(unsigned int);
BYTE buffer[dwLength];
if (!::CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return 1;
if (!::CryptGenRandom(hProvider, sizeof(buffer), &buffer))
{
::CryptReleaseContext(hProvider, 0);
return 1;
}
if (!::CryptReleaseContext(hProvider, 0))
return 1;
return *(unsigned int*)buffer;
}
I have a file.txt where I'm reading each line and I wan't to handle those lines. The file contains IP, Nicknames and some values. I want to save only the IP addresses to another file, but before that I'm checking the result returned by my function (char* get_ip(char arr[])).
The problem is the returned value, it's showing me only a partial, e.g:
normal IP address: 66.55.44.33
My return: 66.55.44
Edit:
There are 2 functions: main() and get_ip()
//<----------- FUNCTION get_ip() -------------------- ><br />
char* get_ip(char buff[]){
char line[32];
for(int i = 0; i < sizeof(buff); i++){
if(buff[i] == '.'){
if(isdigit(buff[i + 1])){
i = 0;
while(buff[i] != ' '){
line[i] = buff[i];
i++;
}
break;
}
}
}
if(isdigit(line[0]))
return line;
else
return 0;
}
//<------------ FUNCTION int main() --------------------->
int main(){
// variable, opening folder etc.
char buff[64], *line;
while(!feof(fph)){
fgets(buff, 63, fph);
line = get_ip(buff);
if(line)
cout << line << "\n";
}
} // main() func. end
Current expected behavior is not defined, as line is a local variable, you are not allowed to return from the function. If you want it to be separate buffer from buff you should use malloc instead of the declaration char line[32];
You should show more code: the signature of you function at least.
You are allocating buff on stack, and then return it.
But arrays are never returned by value, they are decayed to pointer-to-first-element.
That means, that when you use your function like this:
char[32] myFunction(...);
char ip[32] = myFunction(...);
your ip array is initialized with a pointer to array (line) that was destroyed after going out of scope when myFunction returns!
That means, it contains a garbage and you are lucky that you get even partial result from it (although if it was complete garbage you would probably track the problem easier).
The possible remedies is to use std::string (which I recommend) or to pass the pointer to preallocated array to myFunction (C-style solution):
char[32] ip;
myFunction(ip, ...);
One issue might be in the line:
for(int i = 0; i < sizeof(buff); i++){
Specifically the statement
sizeof(buff)
While you might have expected this to return 64, the size of the buffer, you are forgetting how C arrays almost always decay to pointers, so this is actually returning 4( if 32-bit) or 8(if 64-bit), the size of a char *.
You need to explicitly pass in a size.
I am working on multiple producer and Single consumer problem.I wanted to pass Thread like 1,2,3 in the thread function so that individual thread can be named based on these number.
But the program is crashing after count 7 while creating thread.I think problem is due to
variable nThreadNo;
if i limit the count less than 7 it works fine.but if i make count more than this it crashes.
void CEvent1Dlg::CreateProducerThreads()
{
try
{
nThreadNo = new int20];
memset(nThreadNo,0,20);
if (nThreadNo ==NULL) return;
}catch(...)
{
MessageBox(_T("Memory allocation Failed"),_T("Thread"),1);
return ;
}
int i = 0;
for ( i = 0;i<20;i++)
{
//nThreadNo = i+1;
nThreadNo[i] = i+1;
hWndProducer[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ProducerThrdFunc,(void*)(nThreadNo+i),0,&dwProducerThreadID[i]);
if (hWndProducer[i] == NULL)
{
//ErrorHandler(TEXT("CreateThread"));
ExitProcess(3);
}
}
//WaitForMultipleObjects(20,hWndProducer,TRUE,INFINITE);
}
DWORD WINAPI ProducerThrdFunc ( LPVOID n )
{
int *nThreadNo = (int*)n;
char chThreadNo[33];
memset(chThreadNo,0,33);
while(1)
{
itoa(*nThreadNo,chThreadNo,10);
char* pMsg1 = new char[100];
char* pMsg2 = new char[100];
memset(pMsg1,0,100);
memset(pMsg2,0,100);
strcpy(pMsg1,"Producer ");
strcat(pMsg1," Thread No:");
strcat(pMsg1,chThreadNo);
if (stThreadInfoProd.pEventQueue->AddTail(pMsg1)==TRUE)
{
strcpy(pMsg2,"Producer ");
strcat(pMsg2," Thread No:");
strcat(pMsg2,chThreadNo);
strcat(pMsg2," Added the Msg");
}
else
{
strcpy(pMsg2,"Producer ");
strcat(pMsg2," Thread No:");
strcat(pMsg2,chThreadNo);
strcat(pMsg2,"failed to Add the Msg");
}
PostMessage(stThreadInfoProd.hWndHandle,UWM_ONUPDATEPRODUCERLIST,(WPARAM)pMsg2,0);
strcat(pMsg1," Adding Msg:");
//PostMessage(stThreadInfoProd.hWndHandle,UWM_ONUPDATEPRODUCERLIST,(WPARAM)pMsg2,0);
Sleep(3000);
}
return 0;
}
You are zeroing out the first 20 bytes of nThreadNo, not the first 20 * sizeof(int) bytes as you should be doing.
There are other arrays you are indexing into in this code: hWndProducer, dwProducerThreadID. Are there enough elements in those as well?
The CreateThread call is passing the integer value, but the thread function itself is treating it as a pointer to integer. Rather than this:
int *nThreadNo = (int*)n;
It should probably be:
int nThreadNo = (int)n;
Edit: I looked more closely at the call and I do see that it is passing an integer pointer. However, that value is stack data, which may not exist by the time the thread tries to read it. So it should probably just pass the integer value: (void*)(nThreadNo[i])
This line
if (nThreadNo ==NULL) return;
is worthless.
The new operator in modern C++ doesn't return NULL on failure, it throws a std::badalloc exception, but even if you were using an allocator that returns NULL to indicate failure, it's too late to detect it, you're already passed the NULL pointer to memcpy.