Saltar al contenido

¿Cómo trabajar con WinUSB?

Nuestro grupo de especialistas pasados muchos días de trabajo y de juntar de información, obtuvieron la respuesta, esperamos que te sea de utilidad para tu plan.

Solución:

WinUSB consta de dos partes:

  • WinUsb.sys es un controlador en modo kernel que se puede instalar como controlador de función o filtro, por encima de los controladores de protocolo en la pila de dispositivos en modo kernel de un dispositivo USB.
  • WinUsb.dll es una DLL en modo de usuario que expone la API de WinUSB. Las aplicaciones pueden utilizar esta API para comunicarse con WinUsb.sys cuando se instala como controlador de función de un dispositivo. API WinUSB: expuesta por WinUSB.dll. WinUSB se incluye en el Kit de controladores de Windows (WDK) en forma de un paquete de co-instalador, WinUSBCoInstaller.dll, ubicado en WinDDK BuildNumber Redist Winusb.

Para utilizar la API de WinUSB en una aplicación:

  • Incluir WinUsb.h
  • Agregue WinUsb.lib a la lista de bibliotecas que están vinculadas a su aplicación.
  • Usb100.h contiene declaraciones para algunas macros útiles.
  • Utilice el GUID de la interfaz del dispositivo para obtener la ruta del dispositivo. El GUID correcto es el que especificó en el INF que se utilizó para instalar WinUsb.sys.
  • Obtenga un identificador del conjunto de información del dispositivo pasando el GUID de la interfaz del dispositivo que definió en el INF a SetupDiGetClassDevs. La función devuelve un identificador HDEVINFO.
  • Llame a SetupDiEnumDeviceInterfaces para enumerar las interfaces del dispositivo del sistema y obtener información sobre la interfaz de su dispositivo.
  • Llame a SetupDiGetDeviceInterfaceDetail para obtener datos detallados para la interfaz del dispositivo.
  • Llame a la función GetDevicePath para obtener la ruta del dispositivo.
  • Pase la ruta del dispositivo a CreateFile para obtener un identificador de archivo para el dispositivo. Usar ReadFile y WriteFile para comunicarse con el dispositivo.
  • Pase el identificador de archivo a WinUsb_Initialize para inicializar WinUSB y obtener un identificador de WinUSB. Utiliza el identificador de WinUSB del dispositivo para identificar el dispositivo cuando llama a las funciones de la API de WinUSB, no el identificador de archivo del dispositivo.

Para soluciones más avanzadas, utilice las funciones:

  • WinUsb_QueryDeviceInformation para obtener la velocidad del dispositivo.
  • WinUsb_QueryInterfaceSettings para obtener los descriptores de interfaz correspondientes. El identificador de WinUSB corresponde a la primera interfaz.
  • WinUsb_QueryPipe obtiene información sobre cada punto final.
  • WinUsb_WritePipe escribe el búfer en el dispositivo; comportamiento predeterminado: las escrituras de longitud cero se reenvían a la pila. Si la longitud de transferencia es mayor que la longitud máxima de transferencia, WinUSB divide la solicitud en solicitudes más pequeñas de longitud máxima de transferencia y las envía en serie.
  • más funciones e información: http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/winusb_howto.docx

Para fines de depuración, probablemente necesite: winusbtrace_tool https://blogs.msdn.microsoft.com/usbcoreblog/2010/02/05/how-to-generate-and-view-a-winusb-debug-trace-log/; Wireshark https://www.wireshark.org con el complemento USBPcap.

Otro ejemplo: http://searchingforbit.blogspot.com/2012/04/winusb-communication-with-stm32-part-1.html. La plantilla de muestra viene con Visual Studio.

También necesita tener conocimientos de escritura de archivos .inf.

Otra forma fácil de comunicarse con USB: libusb-win32 https://sourceforge.net/projects/libusb-win32/

Mi aplicación de consola de ejemplo simple envía pequeños fragmentos de datos (para mantenerlos vivos) al dispositivo:

#include "stdafx.h"
#include 
#include  
#include  
#include 
#include 
#pragma comment(lib, "hid.lib")
#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "winusb.lib")
#include  


iString DevicePath;
bool                    WinusbHandle_Open=false;
bool                    DeviceHandle_Open = false;
WINUSB_INTERFACE_HANDLE WinusbHandle;
HANDLE                  DeviceHandle;
UCHAR usb_out_buffer[64];
DEFINE_GUID(GUID_DEVCLASS_WINUSB, 0x88bae032L, 0x5a81, 0x49f0, 0xbc, 0x3d, 0xa4, 0xff, 0x13, 0x82, 0x16, 0xd6);
DEFINE_GUID(GUID_DEVCLASS_STL, 0xf177724dL, 0x74d3, 0x430e, 0x86, 0xb5, 0xf0, 0x36, 0x89, 0x10, 0xeb, 0x23);
GUID winusb_guid;
GUID stl_guid;

bool connectusb();
void  disconnectusb();




int main()

    DWORD n;
    DWORD   numEvents;
    HANDLE rHnd;    

WinusbHandle_Open = false;
DeviceHandle_Open = false;
winusb_guid = GUID_DEVCLASS_WINUSB;
stl_guid = GUID_DEVCLASS_STL;
usb_out_buffer[0] = 0;
usb_out_buffer[1] = 1;
usb_out_buffer[2] = 2;
usb_out_buffer[3] = 3;

ULONG bytesWritten;
ULONG timeout;
timeout = 100;
rHnd = GetStdHandle(STD_INPUT_HANDLE);

WinUsb_SetPipePolicy(WinusbHandle, 0x01, PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout);

timeout = TRUE;
WinUsb_SetPipePolicy(WinusbHandle, 0x01, AUTO_CLEAR_STALL, sizeof(ULONG), &timeout);


timeout = TRUE;
WinUsb_SetPipePolicy(WinusbHandle, 0x01, RAW_IO, sizeof(ULONG), &timeout);//Bypasses queuing and error handling to boost performance for multiple read requests.


while (true)
 (!WinusbHandle_Open))  if (!connectusb())Sleep(2000); 
if ((!WinusbHandle_Open) 
disconnectusb();
return 0;





bool connectusb()
 FILE_FLAG_OVERLAPPED,
    NULL);

if (INVALID_HANDLE_VALUE == DeviceHandle) 
    n = GetLastError();


if (INVALID_HANDLE_VALUE == DeviceHandle) return false;
DeviceHandle_Open = true;



if (!WinUsb_Initialize(DeviceHandle, &WinusbHandle))
 
     n = GetLastError();
     CloseHandle(DeviceHandle); DeviceHandle_Open = false;
     return false;
 



WinusbHandle_Open = true;
return true;


void  disconnectusb()

    if (WinusbHandle_Open)  WinUsb_Free(WinusbHandle); WinusbHandle_Open = false; 
    if (DeviceHandle_Open)  CloseHandle(DeviceHandle); DeviceHandle_Open = false; 

  1. Sí, describió correctamente USC CDC ACM.
  2. WinUSB existe para admitir dispositivos que no tienen una clase de dispositivo en particular. Si su dispositivo implementa una clase de dispositivo como Dispositivo de interfaz humana, Dispositivo de almacenamiento masivo o Dispositivo de comunicaciones (CDC), puede usar los controladores que vienen con su sistema operativo para hablar con ese dispositivo. Si desea una interfaz USB más personalizable y flexible que no se ajuste a una de esas clases, puede usar WinUSB para hablar con su dispositivo. También puede escribir su propio controlador si lo desea, pero eso va a ser mucho trabajo y no lo recomendaría. Algunas personas han escrito controladores que son alternativas a WinUSB: puede buscar libusbK, libusb0.sys y UsbDK para ver ejemplos. WinUSB tiene la ventaja de que viene con Windows, por lo que no usaría uno de esos otros controladores a menos que tenga una característica específica que realmente necesita.
  3. Creo que WinUSB_WritePipe envía los datos como un solo USB transferir. A transferir tiene una definición específica en la especificación USB. Puede saber cuándo finaliza una transferencia porque recibirá un paquete corto al final de la transferencia. Un paquete corto es un paquete que es más pequeño que el tamaño máximo de paquete del punto final y posiblemente podría tener una longitud cero. Debería comprobar si eso es realmente true aunque; intente enviar una transferencia que sea un múltiplo del tamaño máximo de paquete y asegúrese de que Windows envíe un paquete de longitud cero al final. Por cierto, debería considerar enviar sus datos como una transferencia de control o una serie de transferencias de control en el punto final 0. Las transferencias de control tienen un concepto integrado de una solicitud y una respuesta a la solicitud. A pesar del nombre, las transferencias de control se pueden utilizar para transferir grandes cantidades de datos; se utilizan comúnmente en los cargadores de arranque USB (consulte la clase DFU). Otra ventaja de usar transferencias de control en lugar de puntos finales distintos de cero es que no tiene que agregar descriptores de puntos finales adicionales e inicializar los puntos finales en su firmware. Su pila USB debe tener la maquinaria para manejar transferencias de control personalizadas y debería poder realizar transferencias de control personalizadas simplemente escribiendo algunas funciones de devolución de llamada.
  4. Para implementar WinUSB en el lado del dispositivo, necesitaría escribir sus propios descriptores USB y luego usar comandos de transferencia USB de bajo nivel para leer y escribir datos desde puntos finales, o para manejar transferencias de control específicas del proveedor en el punto final cero. No estoy familiarizado con las bibliotecas USB STM32, pero debería poder identificar el componente principal que implementa las transferencias de control y los puntos finales IN y OUT, sin hacer nada específico para una clase de dispositivo. Ese es el componente que necesitaría aprender a usar.
  5. De forma predeterminada, debe utilizar WinUSB en lugar de USB CDC ACM. La única razón para usar USB CDC ACM es si su dispositivo es en realidad un puerto serie o si desea facilitar que las personas hablen con su dispositivo en una variedad de lenguajes de programación y entornos. La mayoría de los lenguajes de programación admiten puertos seriales, pero el usuario aún tendría que escribir el código además del que genera su formato de comando particular, por lo que en realidad no le brinda tanto. Un problema con USB CDC ACM es que si el dispositivo se desconecta mientras usted tiene una manija abierta y luego se vuelve a conectar, los diversos controladores USB CDC ACM a menudo pueden entrar en mal estado. En particular, usbser.sys anterior a Windows 10 no maneja bien esto y, por lo general, debe desenchufar y volver a enchufar el dispositivo para que el puerto COM vuelva a ser utilizable. USB CDC ACM utiliza puntos finales masivos para su transferencia de datos, por lo que no hay garantía de latencia. Con WinUSB, tiene la opción de usar puntos finales de interrupción para que pueda estar seguro de que siempre se transferirá un paquete por cada marco USB.

También tengo que hacer exactamente el mismo requisito: PC <==> STM
Microsoft tiene mucha documentación sobre WinUSB. Esto es lo que he visto que responde a sus preguntas …

Muestra de dispositivo USB personalizado
https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CustomUsbDeviceAccess

Desarrollo de aplicaciones de Windows para dispositivos USB: C # Y VB
https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/developing-windows-applications-that-communicate-with-a-usb-device

Aplicación de escritorio de Windows para un dispositivo USB
https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/windows-desktop-app-for-a-usb-device

Cómo acceder a un dispositivo USB mediante las funciones WinUSB
https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/using-winusb-api-to-communicate-with-a-usb-device

Desarrollo de controladores de Windows para controladores de host USB
https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/developing-windows-drivers-for-usb-host-controllers

Windows.Devices.Usb Windows.Devices.Usb Espacio de nombres
https://docs.microsoft.com/en-us/uwp/api/windows.devices.usb

Calificaciones y comentarios

Si conservas algún reparo o capacidad de prosperar nuestro enunciado puedes añadir una apostilla y con gusto lo estudiaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *