La WinUSB de Microsoft

Como sabemos la WinUSB está habilitada en Windows XP, Windows Vista, Windows Server 2008 y Windows 7.

Pero solo viene incluido en el sistema desde Windows Vista; en XP es necesario instalarla.

Tanto la WinUSB y la mpusbapi.dll v1.1.0.0 de Microchip son compatibles con Windows Vista.

Recordemos que la norma USB dispone de 4 tipos para transmisión de datos:

·Control
·Bulk
·Interrupt
·Isochronous

Y varias clases de dispositivos posibles:

·USB audio device
·USB Communications device
·USB human interface device(HID)
·USB printer device
·USB massstorage device
·USB hub device
·USB smart card reader device
·USB video device
·USB wireless device
·Etc.

Pero la WinUSB no soporta el tipo de transmisión Isochronous.

Cuando instalamos la WinUSB se crea el archivo winusb.sys en el directorio del sitema, que es en realidad el driver con el que nuestra aplicación se comunicara para manejar nuestro dispositivo USB; para instalarla son necesarios los siguientes archivos:

1. WinUSBCoInstaller.dll
2. WdfCoInstaller01007.dll
3. Un .inf para instalar la winusb.sys.

Estos archivos deben de coincidir con la arquitectura de la CPU: x86 y x64; y vienen incluidas con la Windows Driver Kid (WDK).

La documentación basica de como realizar todo el proceso para crear el software se puede encontrar en :
“How to Use WinUSB to Communicate with a USB Device.pdf” , la cual tambien adjunto en el archivo del proyecto.

La documentación sobre las funciones de la WinUSB, la podemos encontrar en la ayuda de: Visual Studio, Rad Studio 2009, y en la propia documentación de la Windows Driver Kid (WDK), Solo bastara buscarlas como: “WinUSB User-Mode Client Support Routines”.

La WinUSB consta de 20 funciones, de las cuales muchas solicitan o devuelven parámetros estructurados (record).

A diferencia de la dll de Microchip, esta no posee una función que directamente devuelva el handle al dispositivo USB, la función de la WinUSB: WinUSB_Initialize(), requiere que se le pase el manejador al dispositivo…es decir esto se tiene que hacer a mano; a diferencia de la dll de Microchip,
que para inicializarla solo requería pasarle el VID and PID.

Delphi :


El handle requerido por la WinUSB_Initialize () lo podemos conseguir pasando el path del dispositivo (si revisamos este lo podemos encontrar en el registro de Windows), a la conocida función CreateFile(); hasta aquí todo bien, pero para conseguir este path es necesario hacer uso de varias funciones de la SetupApi.dll, la cual no está importada en Delphi (lo estará en D2009?).

Asi que nos queda 2 alternativas la importamos nosotros mismos o hacemos uso de las fantásticas utilidades del PROJECT JEDI.

La JEDI API Library, (descargar "scapi - Setup & Config Manager API") tiene importadas todas estas funciones (cosa que podríamos hacer pero tal vez no tan eficientemente o podemos inventar nuevamente la rueda),
para usar esta librería de unidades solo tenemos como es costumbre que agregarla a Environment Options\Library\Library path.

Otro detalle es que algunas de las funciones que usamos de la SetupApi necesitan un GUID para la interface del dispositivo (GUID_DEVINTERFACE),
este valor también deberá ser incluido en el archivo INF (MyWinUSB.inf); la forma como el driver winusb.sys se reconoce como controlador de
nuestro dispositivo USB.

Este GUID lo podemos generar haciendo Ctrl+Shift+G (ó Ctrl+Mayus+G) en el editor de Delphi.

 

El projecto consta de 3 unidades: el program en si, la importacion de las funciones de la WinUSB.dll y la unidad en las que se declaran los parametros estructurados para las funciones de la dll.

 

codigo Delphi:

.
.
.
Const


   //La interface GUID ubicada en al seccion [Dev_AddReg] del  .inf
   GUID_DEVINTERFACE: TGUID        = '{9FD6FF49-05EC-49C4-9B78-371937D1E315}';

 

   //constante para la funcion WinUsb_QueryDeviceInformation - referirse a la
   //doc de la WinUSB
   DEVICE_SPEED                    =  $001;
.
.
.
//casi todas las funciones aqui son de la SetupApi
//documentacion al respecto en la ayuda de: visual studio,
//C++/Delphi 2009, Windows Driver Kit(WDK)
function TForm1.GetDevicePath:  THandle;
var
   BytesReturned          : DWORD;
   LPGUID                      : TGUID;
   DeviceInfo                 : HDEVINFO;
   DeviceInterfaceData  : TSPDeviceInterfaceData;
   DetailData                  : PSPDeviceInterfaceDetailData;
begin
  LPGUID := GUID_DEVINTERFACE;
  DetailData:= nil;
  GetDevicePath:= INVALID_HANDLE_VALUE;

 

  //SetupDiGetClassDevs : obtiene un handle hacia la informacion de la device
  DeviceInfo:=SetupDiGetClassDevs(@LPGUID, nil, 0,
                                                        DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
 
  if not(DeviceInfo = Pointer(INVALID_HANDLE_VALUE)) then
  begin


    //inicializa la estructura TSPDeviceInterfaceData
    DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);

    //SetupDiEnumDeviceInterfaces : enumera todas las interfaces de las devices
    if SetupDiEnumDeviceInterfaces(DeviceInfo, nil, LPGUID, 0, DeviceInterfaceData) then
    begin


       //SetupDiGetDeviceInterfaceDetail : obtiene detalles de la informacion de la interface

       //de nuestra device
       //estos datos son almacenados en la estructura TSPDeviceInterfaceDetailData
       if not SetupDiGetDeviceInterfaceDetail(DeviceInfo, @DeviceInterfaceData, nil, 0,
                                                                     BytesReturned, nil) then
       begin
          DetailData := AllocMem(BytesReturned);

 

          if DetailData =  Pointer(INVALID_HANDLE_VALUE) then
          begin
             SetupDiDestroyDeviceInfoList(DeviceInfo);
             GetDevicePath:=INVALID_HANDLE_VALUE;
          end;
          DetailData.cbSize:= SizeOf(TSPDeviceInterfaceDetailData);
 
          //SetupDiGetDeviceInterfaceDetail : obtiene el tamño correcto para la estructura
          //TSPDeviceInterfaceDetailData
          if SetupDiGetDeviceInterfaceDetail(DeviceInfo, @DeviceInterfaceData, DetailData,
                                                                 BytesReturned, BytesReturned, nil) = false   then
          begin
             FreeMem(DetailData);
             GetDevicePath:=INVALID_HANDLE_VALUE;
          end;
 
          if DetailData.DevicePath  =  ' '   then
          begin
             SetupDiDestroyDeviceInfoList(DeviceInfo);
             FreeMem(DetailData);
          end;
 
          //obtenemos un handle para la device
          GetDevicePath := CreateFile(DetailData.DevicePath,
                                      GENERIC_WRITE or GENERIC_READ,
                                      FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,
                                      FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0 );
          FreeMem(DetailData);

       end;

 

    end;

 

  end;

 

end.

 

 

 

Las funciones de la WinUSB nos permiten obtener abundante información sobre el descriptor en el PIC


PIC :

El código en el PIC es el mismo que usamos anteriormente compilado con  PICC: USB_Bulk.

INF :

para detalles sobre el .INF debemos referirnos al apartado "How to Install WinUsb.sys as a Function Driver" del documento
“How to Use WinUSB to Communicate with a USB Device.pdf”

y al capitulo 9 del libro "Usb Complete - Everything You Need To Develop Custom Usb Peripherals" de Jan Alelxon

En el archivo MyWinUSB.inf son importantes los dos GUID que se deben incluir

1. ClassGuid: este valor puede ser eligido de entre los definidos en

C:\WinDDK\6001.18002\inc\api\ devguid.h
(carpeta de instalscion de la WDK); pero se acostumbra usar uno propio.

2. DeviceInterfaceGUIDs en la sección [Dev_AddReg]:
este GUID es el mismo que está incluido en el código Delphi, el GUID para la interface de nuestro dispositivo USB.

Podemos generar un GUID haciendo Ctrl+Shift+G (ó Ctrl+Mayus+G) en el editor de Delphi.

Algo rapido:

1. grabar el .hex en el PIC
2. Al conectar el cable te pedira el driver, elije la carpeta "\My WinUSB with Delphi\PC\Driver".
3. Listo ejecuta MyWinUSB.exe

el proyecto completo se puede descargar de:

My WinUSB con Delphi.rar

 

 

 

 

 

 

 

 

Click para ampliar la imagen.

 

 

 

 

Escribir comentario

Comentarios: 7
  • #1

    Jasiel (sábado, 06 octubre 2012 11:31)

    Please, send again the link of the project, is off-line!

  • #2

    fenixariel (viernes, 19 octubre 2012 01:37)

    Ok lo revisare...

  • #3

    fenixariel (viernes, 19 octubre 2012 01:40)

    el link para My WinUSB con Delphi.rar


    http://www.mediafire.com/download.php?1zs13bc4qx661x1

  • #4

    u=9364 (jueves, 25 abril 2013 11:35)

    This is an excellent post! Thank you for sharing!

  • #5

    Thomas (martes, 12 agosto 2014 02:31)

    existe este link todavia?
    me interesa aprender como funciona USB con Delphi

  • #6

    fenixariel (martes, 12 agosto 2014 16:20)

    De tiempo en tiempo parece que mediafire cambia los link, ya esta el correcto..saludos.

  • #7

    fenixariel (martes, 12 agosto 2014 16:22)

    También tienes que ver USB HID y USB BULK con Delphi