Bueno muchos dirán ......pero es algo muy sencillo de hacer
. La verdad NO, hasta ahora no había tenido ningún tipo de problemas en el uso de la librería mcHID.dl, pero en el camino me he encontrado con dificultades bastante interesantes, una de las cuales voy a tratar de exponer ahora para que alguien que tenga más conocimiento de programación pueda ayudarme.
Lo que trato de descubrir es como detectar la conexión fisica de un dispositivo determinado al host o PC.
mi programa de aplicación tiene un botón en donde nosotros conectamos o desconectamos de manera manual el dispositivo , a su vez tenemos la facilidad de configurar el VID, PID y los tamaños de los buffers de entrada y salida.
La aplicación es la siguiente:
Bueno como se ve en la inmágen podemos configurar los parámetros básicos del USB y tenemos un botón de conección / desconección.
Mi problema radica en cuanto yo desconecto el dispositivo de forma física , es decir desconecto el cable que une el dispositivo con el host ...dicha desconexion no es posible detectarla si el programa de aplicación no está conectado al handler....les muestro mi error..
yo en mi forma de buscar el error me di cuenta que la conexión se detecta mediante una interrupción que produce el dispositivo al enlazarse con el handler ...esta interrupción activa un flag o bandera y en la aplicación la activación de este flag nos indica o no la condición fisica en la que se encuentra nuestro dispositivo.
Paso a mostrarles el código que hace esto posible:
Private Const NOTIFY_PLUGGED As Short = 1 CONECCIÓN DEL DISPOSITIVO
Private Const NOTIFY_UNPLUGGED As Short = 2 DESCONECCIÓN DEL DISPOSITIVO
Private Const NOTIFY_CHANGED As Short = 3
Private Const NOTIFY_READ As Short = 4
En esta porción de código que defini anteriormente se encuentra la función que según la interrupción que produzca el dispositivo se activa alguna de las cuatro banderas....
Ahora el problema radica que estas interrupciones se producen solo cuando la aplicación está conectada al handler....y aqui muestro la función de conección:
Por lo tanto si yo me conecto primero al handler ....si me detecta la conexion fisica o desconección del dispositivo. Miren la aplicación:
Ahora mi pregunta es si se puede detectar primero la conección al host..y luego conectarme...es decir que la aplicación haga un scaneo para ver si hay un dispositivo conectado al host y en funcion de esto conectarme al mismo o no....![Roll eyes :rolleyes: :rolleyes:](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Les dejo los códigos fuente del programa y de la librería:
Lo que trato de descubrir es como detectar la conexión fisica de un dispositivo determinado al host o PC.
mi programa de aplicación tiene un botón en donde nosotros conectamos o desconectamos de manera manual el dispositivo , a su vez tenemos la facilidad de configurar el VID, PID y los tamaños de los buffers de entrada y salida.
La aplicación es la siguiente:
![USB1.jpg](/proxy.php?image=http%3A%2F%2Fi822.photobucket.com%2Falbums%2Fzz150%2FMoyanoJonathan%2FUSB1.jpg&hash=9cafda5915b4685a1af439120e95ac8b)
Bueno como se ve en la inmágen podemos configurar los parámetros básicos del USB y tenemos un botón de conección / desconección.
Mi problema radica en cuanto yo desconecto el dispositivo de forma física , es decir desconecto el cable que une el dispositivo con el host ...dicha desconexion no es posible detectarla si el programa de aplicación no está conectado al handler....les muestro mi error..
![USB2.jpg](/proxy.php?image=http%3A%2F%2Fi822.photobucket.com%2Falbums%2Fzz150%2FMoyanoJonathan%2FUSB2.jpg&hash=4679fc59600a10cf5632e622e4284e84)
yo en mi forma de buscar el error me di cuenta que la conexión se detecta mediante una interrupción que produce el dispositivo al enlazarse con el handler ...esta interrupción activa un flag o bandera y en la aplicación la activación de este flag nos indica o no la condición fisica en la que se encuentra nuestro dispositivo.
Paso a mostrarles el código que hace esto posible:
y su conjunto de flags o banderas definidas:Private Function WinProc(ByVal pHWnd As Integer, ByVal pMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
If pMsg = WM_HID_EVENT Then
Select Case wParam
' HID device has been plugged message...
Case Is = NOTIFY_PLUGGED
HostForm.OnPlugged(lParam)
' HID device has been unplugged
Case Is = NOTIFY_UNPLUGGED
HostForm.OnUnplugged(lParam)
' controller has changed...
Case Is = NOTIFY_CHANGED
HostForm.OnChanged()
' read event...
Case Is = NOTIFY_READ
HostForm.OnRead(lParam)
End Select
End If
' next...
WinProc = CallWindowProc(FPrevWinProc, pHWnd, pMsg, wParam, lParam)
End Function
Private Const NOTIFY_PLUGGED As Short = 1 CONECCIÓN DEL DISPOSITIVO
Private Const NOTIFY_UNPLUGGED As Short = 2 DESCONECCIÓN DEL DISPOSITIVO
Private Const NOTIFY_CHANGED As Short = 3
Private Const NOTIFY_READ As Short = 4
En esta porción de código que defini anteriormente se encuentra la función que según la interrupción que produzca el dispositivo se activa alguna de las cuatro banderas....
Ahora el problema radica que estas interrupciones se producen solo cuando la aplicación está conectada al handler....y aqui muestro la función de conección:
Código:
Public Function ConnectToHID(ByRef targetForm As Form) As Boolean
Dim pHostWin As Integer = targetForm.Handle.ToInt32
FWinHandle = pHostWin
pHostWin = hidConnect(FWinHandle)
FPrevWinProc = DelegateSetWindowLong(FWinHandle, GWL_WNDPROC, Ref_WinProc)
HostForm = targetForm
End Function
![USB3.jpg](/proxy.php?image=http%3A%2F%2Fi822.photobucket.com%2Falbums%2Fzz150%2FMoyanoJonathan%2FUSB3.jpg&hash=745681120b8e1291db492f450f286769)
Ahora mi pregunta es si se puede detectar primero la conección al host..y luego conectarme...es decir que la aplicación haga un scaneo para ver si hay un dispositivo conectado al host y en funcion de esto conectarme al mismo o no....
Les dejo los códigos fuente del programa y de la librería:
Código:
Public Class Form1
Dim VendorID As Short ' Variable que contiene el ID del vendedor del producto USB.
Dim ProductID As Short ' Variable que contiene el ID del producto USB.
Dim phandle As Integer
' Declaración de Buffers de lectura / escritura.
Dim BufferInSize As Short ' Declaramos el tamaño del buffer de entrada.
Dim BufferOutSize As Short ' Declaramos el tamaño del buffer de salida.
Dim BufferIn(BufferInSize) As Byte ' Variable que contiene los datos de salida cuyo tamaño lo designa BufferInSize.
Dim BufferOut(BufferOutSize) As Byte ' Variable que contiene los datos de salida cuyo tamaño lo designa BufferOutSize
Private Sub Hora_windows_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Hora_windows.Tick
StatusStrip1.Items(0).Text = DateTime.Now.ToLongTimeString() ' Mostramos la hora de Windows.
End Sub
Private Sub SalirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SalirToolStripMenuItem.Click
Close() ' Cerramos la aplicación al presionar salir.
DisconnectFromHID() ' Desconectamos el dispositivo USB.
End Sub
Private Sub AutorToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AutorToolStripMenuItem.Click
MessageBox.Show("Pograma de ejemplo Nº1 HID usando mcHID.dll" & vbLf & vbLf & "Autor: Moyano Jonathan." & vbLf & "Contacto: [EMAIL="jonathan215@hotmail.com"]jonathan215@hotmail.com[/EMAIL] " & vbLf & vbLf & "http://www.forosdeelectronica.com" & vbLf & vbLf & "LICENCIA: FREEWARE", "", MessageBoxButtons.OK, MessageBoxIcon.Information) ' Leeme para el usuario.
End Sub
Private Sub LeemeToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LeemeToolStripMenuItem.Click
MessageBox.Show("Programa de ejemplo Nº1 HID:" & vbLf & "Muestra una pantalla de configuración del puerto USB y" & vbLf & "también dentro de un cuadro nos muestra si el" & vbLf & "dispositivo está conectado o no.", "", MessageBoxButtons.OK, MessageBoxIcon.Information) ' Leeme para el usuario.
End Sub
Private Sub Conectar_dispositivo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Conectar_dispositivo.Click
If Conectar_dispositivo.Text = "DESCONECTAR DISPOSITIVO" Then
Conectar_dispositivo.Text = "CONECTAR DISPOSITIVO"
DisconnectFromHID() ' Desconectamos el dispositivo USB de la aplicación.
USB_estado.BackColor = Color.Red
debug.Items.Add("Dispositivo desconetado por el usuario.")
debug.Items.Add("Se puede deconectar el dispositivo del host de forma segura")
ElseIf Conectar_dispositivo.Text = "CONECTAR DISPOSITIVO" Then
ConnectToHID(Me) ' Enlazamos el dispositivo al programa de aplicación.
debug.Items.Add("Dispositivo:")
debug.Items.Add("VID:" & Hex(VendorID))
debug.Items.Add("PID:" & Hex(ProductID))
debug.Items.Add("IN_BUFFER: " & BufferInSize.ToString & " bytes.")
debug.Items.Add("IN_BUFFER: " & BufferOutSize.ToString & " bytes.")
Conectar_dispositivo.Text = "DESCONECTAR DISPOSITIVO"
End If
End Sub
'**********************************************************************
' En caso de que el formulario se cierre el dispositivo se desconecta.
'**********************************************************************
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
DisconnectFromHID()
End Sub
'*****************************************************************
' Un dispositivo USB ha sido conectado.
'*****************************************************************
Public Sub OnPlugged(ByVal pHandle As Integer)
If hidGetVendorID(pHandle) = VendorID And hidGetProductID(pHandle) = ProductID Then
USB_estado.BackColor = Color.Green
debug.Items.Add("El dispositivo ha sido conectado")
End If
End Sub
'*****************************************************************
' Un dispositivo USB ha sido desconectado.
'*****************************************************************
Public Sub OnUnplugged(ByVal pHandle As Integer)
If hidGetVendorID(pHandle) = VendorID And hidGetProductID(pHandle) = ProductID Then
hidSetReadNotify(hidGetHandle(VendorID, ProductID), False)
USB_estado.BackColor = Color.Red
debug.Items.Add("El dispositivo ha sido desconectado")
End If
End Sub
'***********************************************************************
' Llamada a Notificación de cambios en el controlador en caso
' de que todos los dispositivos hallan sido conectados o desconectados.
'***********************************************************************
Public Sub OnChanged()
' Toma el manejador del dispositivo en el cuál estemos interasados, luego
' luego setea esta notificación a 1 - esto asegura que tengamos una lectura.
' Se recibirán notificaciones siempre y cuando hayan datos para leer.
pHandle = hidGetHandle(VendorID, ProductID)
hidSetReadNotify(hidGetHandle(VendorID, ProductID), True)
End Sub
'*****************************************************************
' En un evento de lectura....
'*****************************************************************
Public Sub OnRead(ByVal pHandle As Integer)
If hidRead(pHandle, BufferIn(0)) Then
' Primero leemos el reportID, BufferIn(0)
' Luego los demás bytes son los datos del microcontrolador...
End If
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
USB_estado.BackColor = Color.Blue
debug.Items.Clear() ' Limpiamos la pantalla de debug.
debug.Items.Add("Dispositivo aún no conectado")
End Sub
Private Sub Vid_dispositivo_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Vid_dispositivo.TextChanged
VendorID = (Val(Vid_dispositivo.Text))
End Sub
Private Sub Pid_dispositivo_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Pid_dispositivo.TextChanged
ProductID = (Val(Pid_dispositivo.Text))
End Sub
Private Sub In_USB_buffer_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles In_USB_buffer.TextChanged
BufferInSize = (Val(In_USB_buffer.Text))
End Sub
Private Sub Out_USB_Buffer_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Out_USB_Buffer.TextChanged
BufferOutSize = (Val(Out_USB_Buffer.Text))
End Sub
Public Sub WriteSomeData() ' Si hay un dato listo para enviar...
hidWriteEx(VendorID, ProductID, BufferOut(0))
End Sub
End Class
Código:
Imports System.Threading
Imports System.Runtime.InteropServices
Module HIDDLLInterface
' this is the interface to the HID controller DLL - you should not
' normally need to change anything in this file.
'
' WinProc() calls your main form 'event' procedures - these are currently
' set to..
'
' MainForm.OnPlugged(ByVal pHandle as long)
' MainForm.OnUnplugged(ByVal pHandle as long)
' MainForm.OnChanged()
' MainForm.OnRead(ByVal pHandle as long)
' HID interface API declarations...
Declare Function hidConnect Lib "mcHID.dll" Alias "Connect" (ByVal pHostWin As Integer) As Boolean
Declare Function hidDisconnect Lib "mcHID.dll" Alias "Disconnect" () As Boolean
Declare Function hidGetItem Lib "mcHID.dll" Alias "GetItem" (ByVal pIndex As Integer) As Integer
Declare Function hidGetItemCount Lib "mcHID.dll" Alias "GetItemCount" () As Integer
Declare Function hidRead Lib "mcHID.dll" Alias "Read" (ByVal pHandle As Integer, ByRef pData As Byte) As Boolean
Declare Function hidWrite Lib "mcHID.dll" Alias "Write" (ByVal pHandle As Integer, ByRef pData As Byte) As Boolean
Declare Function hidReadEx Lib "mcHID.dll" Alias "ReadEx" (ByVal pVendorID As Integer, ByVal pProductID As Integer, ByRef pData As Byte) As Boolean
Declare Function hidWriteEx Lib "mcHID.dll" Alias "WriteEx" (ByVal pVendorID As Integer, ByVal pProductID As Integer, ByRef pData As Byte) As Boolean
Declare Function hidGetHandle Lib "mcHID.dll" Alias "GetHandle" (ByVal pVendoID As Integer, ByVal pProductID As Integer) As Integer
Declare Function hidGetVendorID Lib "mcHID.dll" Alias "GetVendorID" (ByVal pHandle As Integer) As Integer
Declare Function hidGetProductID Lib "mcHID.dll" Alias "GetProductID" (ByVal pHandle As Integer) As Integer
Declare Function hidGetVersion Lib "mcHID.dll" Alias "GetVersion" (ByVal pHandle As Integer) As Integer
Declare Function hidGetVendorName Lib "mcHID.dll" Alias "GetVendorName" (ByVal pHandle As Integer, ByVal pText As String, ByVal pLen As Integer) As Integer
Declare Function hidGetProductName Lib "mcHID.dll" Alias "GetProductName" (ByVal pHandle As Integer, ByVal pText As String, ByVal pLen As Integer) As Integer
Declare Function hidGetSerialNumber Lib "mcHID.dll" Alias "GetSerialNumber" (ByVal pHandle As Integer, ByVal pText As String, ByVal pLen As Integer) As Integer
Declare Function hidGetInputReportLength Lib "mcHID.dll" Alias "GetInputReportLength" (ByVal pHandle As Integer) As Integer
Declare Function hidGetOutputReportLength Lib "mcHID.dll" Alias "GetOutputReportLength" (ByVal pHandle As Integer) As Integer
Declare Sub hidSetReadNotify Lib "mcHID.dll" Alias "SetReadNotify" (ByVal pHandle As Integer, ByVal pValue As Boolean)
Declare Function hidIsReadNotifyEnabled Lib "mcHID.dll" Alias "IsReadNotifyEnabled" (ByVal pHandle As Integer) As Boolean
Declare Function hidIsAvailable Lib "mcHID.dll" Alias "IsAvailable" (ByVal pVendorID As Integer, ByVal pProductID As Integer) As Boolean
' windows API declarations - used to set up messaging...
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Integer, ByVal hwnd As Integer, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Integer, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
Delegate Function SubClassProcDelegate(ByVal hwnd As Integer, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Public Declare Function DelegateSetWindowLong Lib "USER32.DLL" Alias "SetWindowLongA" _
(ByVal hwnd As Integer, ByVal attr As Integer, ByVal lval As SubClassProcDelegate) As Integer
' windows API Constants
Public Const WM_APP As Integer = 32768
Public Const GWL_WNDPROC As Short = -4
' HID message constants
Private Const WM_HID_EVENT As Decimal = WM_APP + 200
Private Const NOTIFY_PLUGGED As Short = 1
Private Const NOTIFY_UNPLUGGED As Short = 2
Private Const NOTIFY_CHANGED As Short = 3
Private Const NOTIFY_READ As Short = 4
' local variables
Private FPrevWinProc As Integer ' Handle to previous window procedure
Private FWinHandle As Integer ' Handle to message window
Private Ref_WinProc As New SubClassProcDelegate(AddressOf WinProc)
Private HostForm As Object
' Set up a windows hook to receive notification
' messages from the HID controller DLL - then connect
' to the controller
Public Function ConnectToHID(ByRef targetForm As Form) As Boolean
Dim pHostWin As Integer = targetForm.Handle.ToInt32
FWinHandle = pHostWin
pHostWin = hidConnect(FWinHandle)
FPrevWinProc = DelegateSetWindowLong(FWinHandle, GWL_WNDPROC, Ref_WinProc)
HostForm = targetForm
End Function
' Unhook from the HID controller and disconnect...
Public Function DisconnectFromHID() As Boolean
DisconnectFromHID = hidDisconnect
SetWindowLong(FWinHandle, GWL_WNDPROC, FPrevWinProc)
End Function
' This is the procedure that intercepts the HID controller messages...
Private Function WinProc(ByVal pHWnd As Integer, ByVal pMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
If pMsg = WM_HID_EVENT Then
Select Case wParam
' HID device has been plugged message...
Case Is = NOTIFY_PLUGGED
HostForm.OnPlugged(lParam)
' HID device has been unplugged
Case Is = NOTIFY_UNPLUGGED
HostForm.OnUnplugged(lParam)
' controller has changed...
Case Is = NOTIFY_CHANGED
HostForm.OnChanged()
' read event...
Case Is = NOTIFY_READ
HostForm.OnRead(lParam)
End Select
End If
' next...
WinProc = CallWindowProc(FPrevWinProc, pHWnd, pMsg, wParam, lParam)
End Function
End Module