8/10/2008 7:47 El Bruno

[TFS] TFS Missile Build Launcher (2da Parte, lanzando el misil)

Buenas,

en mi post anterior comenté parte de mi proyecto para asegurar la calidad en los proyectos de software:

Lanzador de misiles inalámbrico USB disparado por eventos de un servidor Team Foundation Server 2008.

Una vez visto cómo interceptar eventos en Team Foundation Server 2008, y cómo procesar los mismos; en este post dejaré un poco de lado a TFS e intentaré comentar un poco sobre la tecnología necesaria para trabajar con dispositivos HID con mi humilde y escaso conocimiento al respecto.

Envío de Mensajes a un dispositivo HDI

El siguiente paso fue conocer un poco como funcionan los Human Interface Device (HID), que es el tipo de dispositivos que Windows reconoce usualmente cuando conectamos un ratón, un teclado, etc. a nuestro ordenador.

Debido a que mi flamante lanza misiles USB, no posee un SDK ni nada por el estilo, tuve que empezar desde cero con el método “prueba/error” a descubrir como interactuar con el mismo desde código manejado .Net. Por suerte, en The HID Page existe mucha información sobre como trabajar con HIDs.

Después de varios BSOD, llegué a descubrir que para mi modelo en particular de lanza misiles inalámbrico USB o dispositivo HID, esta información era la que necesitaba para identificar al mismo dentro de la lista de dispositivos en mi laptop:

1 #Region "USB Product Details" 2 3 ' define USB Product and Vendor Id 4 Private usbVendorID As Int16 = Convert.ToInt16(Val("&h4400")) 5 Private usbProductID As Int16 = Convert.ToInt16(Val("&h514")) 6 7 #End Region

Utilizando los valores anteriores, la conexión con el dispositivo se puede realizar iterando a través de los dispositivos locales del ordenador con la siguiente función, donde en la línea 13 obtengo la información del dispositivo y en la línea 18 verifico si corresponde a mi dispositivo:

1 memberIndex = 0 2 Do 3 4 ' Creates a handle to get and compare information for the search of the specified device 5 hidHandle = CreateFile(devicePathName(memberIndex), 0, FILE_SHARE_READ Or FILE_SHARE_WRITE, Nothing, OPEN_EXISTING, 0, 0) 6 7 If Not (hidHandle.IsInvalid) Then 8 9 ' The returned handle is valid, check for the product and vendor 10 MyHid.DeviceAttributes.Size = Marshal.SizeOf(MyHid.DeviceAttributes) 11 12 ' get device information to check for the Product and Vendor ID 13 success = HidD_GetAttributes(hidHandle, MyHid.DeviceAttributes) 14 15 deviceFound = False 16 If success Then 17 ' Find out if the device matches the one we're looking for. 18 If (MyHid.DeviceAttributes.VendorID = usbVendorID) And (MyHid.DeviceAttributes.ProductID = usbProductID) Then 19 deviceFound = True 20 ' Save the DevicePathName for OnDeviceChange(). 21 myDevicePathName = devicePathName(memberIndex) 22 Else 23 ' It's not a match, so close the handle. 24 hidHandle.Close() 25 End If 26 Else 27 ' There was a problem in retrieving the information. 28 hidHandle.Close() 29 End If 30 31 End If 32 33 ' Keep looking until we find the device or there are no devices left to examine. 34 memberIndex = memberIndex + 1 35 Loop Until (deviceFound Or (memberIndex = devicePathName.Length)) 36 37 ' The device was detected. Register to receive notifications if the device is removed or attached. 38 success = MyDeviceManagement.RegisterForDeviceNotifications(myDevicePathName, _parentForm.Handle, hidGuid, deviceNotificationHandle) 39 40 ' Learn the capabilities of the device. 41 MyHid.Capabilities = MyHid.GetDeviceCapabilities(hidHandle) 42 43 If success Then 44 ' Find out if the device is a system mouse or keyboard. 45 hidUsage = MyHid.GetHidUsage(MyHid.Capabilities) 46 47 ' Get the Input report buffer size. 48 _inputReportBufferSize = GetInputReportBufferSize() 49 50 ' Get handles to use in requesting Input and Output reports. 51 readHandle = CreateFile(myDevicePathName, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, Nothing, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0) 52 53 If readHandle.IsInvalid Then 54 exclusiveAccess = True 55 Else 56 writeHandle = CreateFile(myDevicePathName, GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, Nothing, OPEN_EXISTING, 0, 0) 57 ' Flush any waiting reports in the input buffer. (optional) 58 MyHid.FlushQueue(readHandle) 59 End If 60 End If

Una vez finalizado el proceso de búsqueda del dispositivo, los Handles de lectura y escritura del mismo me servirán para posteriores acciones con el HDI (líneas 51 y 56).

Y fue en este punto donde me encontré con uno de los grandes problemas, averiguar que secuencia de información debía enviar a mi lanza misiles para que respondiera a mis órdenes y así comenzar el proyecto de la dominación mundial.

Una vez más el proceso de prueba/error me ayudó a encontrar los siguientes valores en Bytes necesarios para interactuar con el dispositivo:

1 #Region "Byte Action Constants" 2 3 ' byte actions 4 Public usbMissileStop() As Byte = {0, 0} 5 Public usbMissileMoveUp() As Byte = {0, 2} 6 Public usbMissileMoveDown() As Byte = {0, 1} 7 Public usbMissileMoveLeft() As Byte = {0, 4} 8 Public usbMissileMoveRight() As Byte = {0, 8} 9 Public usbMissileReset() As Byte = {0, 83} 10 Public usbMissileFire() As Byte = {0, 99} 11 12 #End Region 13

Una vez obtenidos los handles para trabajar con el HID, el envío de información es una tarea bastante simple esto es fácil decirlo ahora después de estar toda una tarde cruzando los dedos para no perder nada después de los BSOD. En el siguiente fragmento de código en la línea 9, escribo un buffer de Bytes al dispositivo:

1 ' Set the size of the Output report buffer (array begins at index 0) 2 ReDim outputReportBuffer(MyHid.Capabilities.OutputReportByteLength - 1) 3 4 ' Store the report ID in the first byte of the buffer: 5 outputReportBuffer = buffer 6 7 ' Use WriteFile to send the report. If the HID has an interrupt OUT endpoint, WriteFile uses an interrupt transfer to send the report. If not, WriteFile uses a control transfer. 8 Dim myOutputReport As New Hid.OutputReportViaInterruptTransfer 9 success = myOutputReport.Write(outputReportBuffer, writeHandle)

Con toda la información anterior y tirando de mis pocas dotes para el diseño de sistemas, pude diseñar una clase UsbManager para gestionar el lanza misiles USB con la siguiente interfaz, que me permite mover el lanzamisiles en todas direcciones, disparar el mismo y resetearlo a la posición inicial.

Con esta clase creada y después de un par de Clicks al estilo Visual Basic .Net, creé la siguiente aplicación con la que puedo reemplazar a la aplicación original para el lanzamisiles. Como se puede ver en la siguiente imagen en la misma, he incluido un control de dirección y de disparo; un par de botones para detener y resetear el lanzamisiles y finalmente, una opción para definir el período de tiempo de delay entre movimientos:

 

Como se puede apreciar en la  imagen, el formulario es bastante simple, pero cumple su cometido. Y si una imagen vale más de mil palabras, el siguiente vídeo vale 25 BSOD:

VB.Net USB Missile Launcher

En el próximo post, mostraré como organizar todos los componentes: el suscriptor de eventos de Team Foundation Server 2008, el UsbManager para el lanzamisiles, el proxy de intercepción de eventos, y el gestor de localización de desarrolladores, para tener el modelo completo y en funcionamiento.

Descarga del proyecto de ejemplo: USB%20Missile%20Launcher-05.zip

Referencias

Crossposting from ElBruno.com
Archivado en: ,,
Comparte este post:

# [#KINECTSDK] Kinect Missile Launcher (I): Identificando el dispositivo HID

Sunday, April 22, 2012 9:07 PM by El Bruno

Buenas Hace 2 semanas que estamos jugando con el Valentino al Kinect Star Wars y tengo que admitir que