odczytywanie danych z USB w Windows

0

Witam.

Próbuję odczytać coś z USB za pomocą Win API. Wcześniej inicjializuję sobie wszystko tak jak jest w tutorialu na stronie MSD traktującym o obsłudze USB: http://msdn.microsoft.com/en-us/library/windows/hardware/ff540174(v=vs.85).aspx

Urządzenie inicjalizuje się poprawnie. Wszystkie kroki wykonują się poprawnie. Problem występuje, kiedy chce odczytać coś za pomocą funckji WinUsb_ReadPipe(). Wywołuję ją w następujący sposób:
WINUSB_INTERFACE_HANDLE hDeviceHandle;
UCHAR* szBuffer = (UCHAR*)LocalAlloc(LPTR, sizeof(UCHAR)*cbSize);

UCHAR pID =130;
ULONG cbSize = 1024;// lub 512 - nie ma znaczenia
ULONG cbRead = 0;
Result = WinUsb_ReadPipe(this->hDeviceHandle, this->pID, szBuffer, cbSize, &cbRead, NULL);
 

hDeviceHandle jest wskaźnikiem wykorzystywanym do inicializacji urządzenia(nie jest równy NULL ani INVALID_HANDLE_VALUE),ostatni parametr jest opcjonalny.

W miejscu wywołania funkcji WinUsb_ReadPipe mam błąd (z pewnych względów jestem zmuszony debugować wersję realesową w gdb (mingw):

Program received signal SIGEGV, Segmentation fault.
0x1000020f8 in WinUsb_ReadPipe () from C:\Windows\system32\winusb.dll
<gdb> Exception condition detected on fd 0
error detected on stdin

Czy ktoś ma pomysł dlaczego tak się dzieje ?

dzięki :)

0
... = (UCHAR*)LocalAlloc(..., sizeof(UCHAR) * cbSize); // (1)
 

ULONG cbSize = 1024;// lub 512 - nie ma znaczenia // (2)

... = WinUsb_ReadPipe(..., cbSize, ...);

cbSize z pozycji 1 ma taką samą wielkość co z pozycji 2? Czy obiekt this istnieje w trakcie wywoływania WinUsb_ReadPipe?

0

cbSize jest zadeklarowane już wcześnej przed zaalokowaniem pamięci do tablicy. Źle przekleiłem. Obiekt oczywiście istnieje w trackcie wywołania WinUsb_ReadPipe.

0

Nie o to pytałem, bo domyśliłem się że cbSize (1) jest to gdzieś tam zdefiniowane. Chodzi mi o to, czy alokujesz tyle pamięci, ile podajesz funkcji WinUsb_ReadPipe w czwartym parametrze.

Po co definiujesz (i cytujesz) uchwyt hDeviceHandle, jeśli nie korzystasz z niego? (zakładam, że this->hDeviceHandle to nie ten sam uchwyt)

0

Alokuje nawet więcej więcej pamięci niż podaje w czwartym parametrze. Racja, niepotrzbnie zacytowałem deklarację tego uchwytu, ponieważ jest to ten sam uchwyt co ten podawany jako parametr.

Dodam jeszcze, że wywołuję tą funkcję w wątku, który tworze przy pomocy biblioteki boost. Zastanawiam się czy czasami tutaj nie ma jakiegoś problemu, ponieważ np wątek nie ma praw dostępu do tego miejsca w pamięci. Tylko funkcja czytająca jest wykonywana w wątku. Cała inicjalizacja wykonuje się w głownym wątku programu.

0

Wrzuciłem całą inicializację do jednego wątku - inne funkcje mają dostęp więc to nie jest problem praw dostępu. Segmentation fault dalej występuje na WinUsb_ReadPipe :/

0

Cały czas nie wiem, jak się mają do siebie pID z this->pID i hDeviceHandle z this->hDeviceHandle. Podaj więcej kodu, chodzi głównie o umiejscowienie poszczególnych funkcji, pól i zmiennych w klasie i jej metodach.

0

Proszę bardzo :) :

 

class UsbAPI {
	
public:

	WINUSB_INTERFACE_HANDLE hDeviceHandle;
	WINUSB_INTERFACE_HANDLE hWinUSBHandle;

	//UsbAPI();
	UsbAPI ();
	virtual ~UsbAPI();
	void sendBuf( );
	void emptyBuf( );
	int initializeUsb();
	//friend std::ostream & operator << (Logger &logger, const  logType);
	friend class Logger;
	/* Functions */
	// PRE:     Function is called from main loop as the return value
	// POST:    User is bid farewell before exiting and errors are reported if errorFlag != 0
	static int ExitProgram( bool errorFlag );
	
	BOOL SendDatatoDefaultEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle);
	void ReadPipe(int &idX,std::vector<std::vector<UCHAR> > &myVector);
	bool WritePipe(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG* pcbWritten); // unused function. 

	// PRE:     phWinUsbHandle must not represent -log(H) ... :)
	// POST:    WinUSB fills out the interface handle using the device handle provided.
	//              Errors are returned as any non-zero value
	bool startWinUSB( HANDLE hDeviceHandle, WINUSB_INTERFACE_HANDLE* phWinUSBHandle );
	bool findEndpoints(WINUSB_INTERFACE_HANDLE hDeviceHandle);

	// PRE:     hDeviceHandle must be unused and NULL
	// POST:    WinUsb will search the registry for matching devices installed with the GUID.
	//              If a matching device is found, the provided PHANDLE will be filled with
	//              the matching device's information (location, name, etc...).
	bool searchGUID(GUID guidDeviceInterface, PHANDLE hDeviceHandle);

private:

	
	UCHAR pID;
	ULONG cbSize;
	ULONG cbRead;
	GUID deviceGUID;

	UCHAR  PipeInId;
	UCHAR  PipeOutId;
	UCHAR  PipeInterruptFirst;
	UCHAR  PipeInterruptLast;
	UCHAR  PipeControl;
};




0

Jeszcze metodę z wywołaniem WinUsb_ReadPipe.

0
void UsbAPI::ReadPipe(int & idX,std::vector<std::vector<UCHAR> > & subBuf)
{
	if( hDeviceHandle == INVALID_HANDLE_VALUE )
		cout << "Error because of hDeviceHandle == INVALID_HANDLE_VALUE" <<endl;
 
	cout << "\n\nAttempting to read from pipe:" << (int)this->pID << endl;
	
	BOOL Result;
	DWORD Error;
	//cbSize = 65536*32;
	cbSize=10;
	UCHAR* szBuffer = (UCHAR*)LocalAlloc(LPTR, sizeof(UCHAR)*cbSize);
	UCHAR buffor[900];

	//szBuffer = (BYTE*)LocalAlloc(LPTR, cbSize);
	ULONG cbReadr;
	//UCHAR szBuffer[2024] = {0};

	if ( szBuffer == NULL ) 
		cout <<"szbuff == null"<<endl;
	else 
		cout <<"szbuff !=null"<<endl;

	if(this-hDeviceHandle==NULL)
		cout << "hDeviceHandle null"<<endl;
	else
		cout << "hdevHandle:" << this->hDeviceHandle <<endl;
	if (this->pID ==NULL)
		cout << "pID null"<<endl;
	else 
		cout <<"piD:"<<(int)this->pID<<endl;

	if(this->cbSize==NULL)
		cout << "cbSize null"<<endl;
	else
		cout << "cbSize:"<<this->cbSize<<endl;
	if(&this->cbRead == NULL) 
		cout << "cbRead null"<<endl;
	else
		cout << "cbRead:" << this->cbRead << endl;

	OVERLAPPED ov[ 2 ];
	HANDLE event_list[ 2 ];
	ZeroMemory( &ov[0], sizeof(ov[0]));
	ZeroMemory( &ov[1], sizeof(ov[1]));
	event_list[0] = ov[0].hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
	event_list[1] = ov[1].hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);

	Result = WinUsb_ReadPipe(this->hDeviceHandle, this->pID, buffor, cbSize, &cbReadr, &ov[0]);
	
	if( !Result )
	{
		Error = GetLastError();
		cout << " error.\n    Unable to read from pipe %d. Error %d" << this->pID << Error << endl;
		Logger::getInstance()->logging(Error,"Unable to read from pipe");
	}

	cout << "Read from pipe:" << (int)pID << szBuffer << cbRead << endl;
	Logger::getInstance()->logging(Error,"Reading from pipe success");
}
0

Dwie sprawy:

  • w metodzie tworzysz dwa zdarzenia (event), ale nigdzie ich nie zwalniasz. To poważny wyciek zasobów. W sumie po co dwa zdarzenia, nie wystarczy jedno?
  • z tego co widzę WinUsb_ReadPipe działa w trybie asynchronicznym, a Twój kod jest pisany tak, jakby to była funkcja synchroniczna (blokująca). We wcześniejszym kodzie nie było parametru ov. Teraz na pewno jest błąd, ponieważ Twoja funkcja nie czeka na zakończenie czytania z urządzenia USB, a w parametrach WinUsb_ReadPipe podałeś adresy lokalnych zmiennych.

Tyle mi się rzuciło w oczy, może jest coś jeszcze, ale na razie popraw te błędy, o których pisałem.

0

Ok poprawiłem to, ale nie to było przyczyną. Problem polegał na tym, że przekazywałem zły handler device. zamiast tego wyżej powinien być przekazywany handler hWinUsbHandle, który jest przekazywany wcześniej np w WinUsb_SetPipePolicy.

dzięki za chęci :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1