Newsgroup: it.comp.programmare.win32
Titolo: accesso a USB

Salve a tutti,
sto scrivendo un software in C# che deve accedere a un dispositivo USB
simultaneamente in lettura e scrittura. Più precisamente deve inviare
un flusso di messaggi con un ritardo di 30ms l'uno dall'altro e allo
stesso tempo leggere il flusso di messaggi provenienti dal
dispositivo, che saranno in numero maggiore rispetto a quelli inviati.
E' la prima volta che lavoro in questo settore e ho le idee un po'
confuse. Di seguito viene presentato quello che ho fatto. Il tutto
funziona, ma non bene: ad alte velocità se scrivo non riesco a leggere
e non so so dove ciò che ho scritto è sbagliato.
Grazie in anticipo.
------------------------------------
Ho creato un handle per il dispositivo con CreateFile usando la
struttura OVERLAPPED.
Un thread sta continuamente in ascolto per l'arrivo di messaggi (di
seguito parte del codice per l'esecuzione di ReadFile):
	ApiStructures.SECURITY_ATTRIBUTES security = new
ApiStructures.SECURITY_ATTRIBUTES();
	security.lpSecurityDescriptor = 0;
	security.bInheritHandle = System.Convert.ToInt32(true);
	security.nLength = Marshal.SizeOf(security);
	int eventHandle = ApiFunctions.CreateEvent(ref security, true, true,
"read event");
	ApiStructures.OVERLAPPED overlapped = new ApiStructures.OVERLAPPED();
	overlapped.Offset = 0;
	overlapped.OffsetHigh = 0;
	overlapped.hEvent = eventHandle;
	result = ApiFunctions.ReadFile(readHandle, ref readBuffer[0],
readBuffer.Length, ref readedByteNumber, ref overlapped);
	if (result == 0)
	{
	    if (ApiFunctions.GetLastError() == ApiConstants.ERROR_IO_PENDING)
	    {
	        ApiFunctions.WaitForSingleObject(eventHandle, 1000000);
	        result = ApiFunctions.GetOverlappedResult(readHandle, ref
overlapped, ref readedByteNumber, true);
	        if (result == 0)
	        {
	            readBuffer = null;
	        }
	        ....
Dall'altra parte un thread si occupa i scrivere i messaggi sul
dispositivo USB (di seguito parte del codice per il WriteFile):
	ApiStructures.SECURITY_ATTRIBUTES security = new
ApiStructures.SECURITY_ATTRIBUTES();
	security.lpSecurityDescriptor = 0;
	security.bInheritHandle = System.Convert.ToInt32(true);
	security.nLength = Marshal.SizeOf(security);
	int eventHandle = ApiFunctions.CreateEvent(ref security, true, true,
"write event");
	ApiStructures.OVERLAPPED overlapped = new ApiStructures.OVERLAPPED();
	overlapped.Offset = 0;
	overlapped.OffsetHigh = 0;
	overlapped.hEvent = eventHandle;
	result = ApiFunctions.WriteFile(readHandle, ref reportBuffer[0],
reportBuffer.Length, ref writedBytes, ref overlapped);
	if (result == 0) //errore nella scrittura
	{
	    if (ApiFunctions.GetLastError() == ApiConstants.ERROR_IO_PENDING)
	    {
	        int resultWait =
ApiFunctions.WaitForSingleObject(eventHandle, 100000);
	        ...

e non so so dove ciò che ho scritto è sbagliato.
Non ho letto il codice, ma penso che, usando un thread con lo
stesso handle di lettura/scrittura, il problema sia di
sincronizzazione. Quindi ti consiglio di leggere la
documentazione di queste API:
 InitializeCriticalSection
 DeleteCriticalSection
 EnterCriticalSection
 LeaveCriticalSection
e un esempio (stupido) da MSDN:
http://msdn2.microsoft.com/en-us/library/ms686908.aspx

 sincronizzazione.
Innanzitutto ti ringrazio molto per la risposta. Ci sono però alcune
cose che non mi sono chiare:
  - dovendo leggere e scrivere è meglio usare un unico handle oppure
due?
  - utilizzando uno o due handle va comunque usata la struttura
overlapped?
Grazie ancora.

overlapped?
La struttura OVERLAPPED e' fatta apposta per usare un solo handle
e non avere problemi di lettura/scrittura contemporanei
(asincroni), eventi che spesso capitano fra thread. Per questo
motivo ricevi come errore un ERROR_IO_PENDING o un
ERROR_IO_INCOMPLETE, e puoi usare API come la
GetOverlappedResult. Occorre entrare nell'ordine di idee che il
sistema operativo non gradisce una lettura e una scrittura nello
stesso momento, e purtroppo tocca a noi risolvere il problema
aggiungendo codice... :°(
Uno spunto lo puoi trovare leggendo questo esempio per la
gestione di una porta seriale:
http://msdn2.microsoft.com/en-us/library/ms810467.aspx