Pregunta CreateFileA no puede abrir el dispositivo HID en Windows


EDITAR: problema informado aquí: https://github.com/signal11/hidapi/issues/276

Inkling es un dispositivo de bolígrafo de Wacom. (InklingReader) es un proyecto de código abierto que obtiene datos en tiempo real de él.

Estoy tratando de arreglar InklingReader para usar HIDAPI más bien que libusb  (ya que funciona en un nivel superior: HID en lugar de USB sin procesar, por lo que es mucho más compacto y adecuado. También libusb falla en OSX reciente).

HID API una lib pequeña: una .h, una (por plataforma) .c.

Mi código se ve así:

    unsigned short  inklingVendorId = 0x056a, inklingProductId = 0x0221;
    if (hid_init() == FAIL) return;   
    handle = hid_open(inklingVendorId, inklingProductId, nullptr);

En Windows hid_open falla Paso único revela el punto de falla aquí:

// path = "\\\\?\\hid#vid_056a&pid_0221&mi_00&col01#8&1ea90857&0&0000#"
//        "{4d1e55b2-f16f-11cf-88cb-001111000030}"
//
static HANDLE open_device(const char *path, BOOL enumerate)
{
    HANDLE handle;
    DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ);
    DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;

    // enumerate = 0
    handle = CreateFileA(path,
        desired_access,
        share_mode,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
        0);

    int err = GetLastError(); // 5 i.e. ERROR_ACCESS_DENIED

    return handle; // returns 0xffffffff i.e. INVALID_HANDLE
}

Ahora el autor de HIDAPI dice: "HIDAPI no funcionará con teclados y ratones en Windows. Windows como medida de seguridad no permite la apertura de Mouse y HID de teclado". (aquí)

Y si enumero dispositivos HID:

    struct hid_device_info *devs, *cur_dev;

    devs = hid_enumerate(inklingVendorId, inklingProductId);
    cur_dev = devs;
    while (cur_dev) {
        DBG2("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
        DBG2("");
        DBG2("  Manufacturer: %ls", cur_dev->manufacturer_string);
        DBG2("  Product:      %ls", cur_dev->product_string);
        DBG2("  Release:      %hx", cur_dev->release_number);
        DBG2("  Interface:    %d",  cur_dev->interface_number);
        DBG2("  Usage Page:   %d", cur_dev->usage_page);
        DBG2("  Usage:        %d", cur_dev->usage);
        DBG2("");
        cur_dev = cur_dev->next;
    }
    hid_free_enumeration(devs);

... Recibo no una, sino DOS entradas:

Device Found
  type: 056a 0221
  path: \\?\hid#vid_056a&pid_0221&mi_00&col01#8&1ea90857&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
  serial_number: 2B0400001C90C22A0002DD07FE8B022A

  Manufacturer: Wacom, Inc.
  Product:      MSC Device
  Release:      1256
  Interface:    0
  Usage Page:   1
  Usage:        2

Device Found
  type: 056a 0221
  path: \\?\hid#vid_056a&pid_0221&mi_00&col02#8&1ea90857&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}
  serial_number: 2B0400001C90C22A0002DD07FE8B022A

  Manufacturer: Wacom, Inc.
  Product:      MSC Device
  Release:      1256
  Interface:    0
  Usage Page:   13
  Usage:        2

(Nota: ¡OSX solo informa la SEGUNDA entrada! ¡En OSX no hay problema!)

Comparando path:
ruta: \? \ hid # vid_056a & pid_0221 & mi_00 &col01# 8 y 1ea90857 & 0 &0000# ...
ruta: \? \ hid # vid_056a & pid_0221 & mi_00 &col02# 8 y 1ea90857 & 0 &0001# ...

Según http://www.usb.org/developers/hidpage/Hut1_12v2.pdf,

UsagePage / Usage = 1/2 = {Generic Desktop Controls} / {Mouse}.
UsagePage / Usage = 13/2 = {Digitizers} / {Pen}.

(EDITAR: a veces la primera ruta es 1/2 y la segunda es 13/2, otras veces se intercambia).

Y HIDAPI es solo tomando el primero que encuentre.

Entonces parece que esta debería ser la solución. The Inkling estaba exponiendo 2 'dispositivos' y hidapi estaba tomando el incorrecto (mouse), y Windows no permite el acceso a los dispositivos Mouse o Keyboard.

Así que retoqué el código ...

while (cur_dev) {
    if (cur_dev->vendor_id == vendor_id &&
        cur_dev->product_id == product_id &&
        cur_dev->usage_page == 13) 
    {

... para obtener la entrada correcta, debería funcionar, ¿verdad?

No, CreateFileA solo genera un error diferente:

use_page == 1 => Código de error 5 (ERROR_ACCESS_DENIED)
use_page == 13 => Código de error 32 (ERROR_SHARING_VIOLATION)

Meh. Esto es bastante molesto. ¡Parece que estoy en un callejón sin salida!

He intentado juguetear con los parámetros de CreateFileA, p. reemplazando GENERIC_READ | GENERIC_WRITE  con STANDARD_RIGHTS_READ | STANDARD_RIGHTS_WRITE - Ahora felizmente crea un mango. Pero subsecuente hid_read-s no pueden recopilar ningún dato.

Googlear, https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/af869f90-7bda-483d-ba2d-51680073fe9f/createfile-returns-invalid-handle-while-trying-to-access-hid-device- ¿en-windows-8-desktop-app? forum = wdk parece contener un par de soluciones sugeridas:

ambos tostadora y luciérnaga puede trabajar en la pila HID. tostadora muestra cómo   para abordar el filtro a través de una DOP en bruto, la luciérnaga muestra cómo acceder   con WMI. Desde una perspectiva C, creo que la PDO en bruto es mucho más simple   para codificar, WMI es un poco desagradable y complicado.

luciérnaga
tostadora

El autor está recomendando algo en Tostador, pero es un gran CodeBase y no tengo experiencia con la programación de Windows Driver.

Parece que voy a tener que cavar en un territorio muy desconocido para que todo funcione, así que antes de comenzar, estoy preguntando aquí. Si nadie responde y lo resuelvo, responderé mi propia pregunta.

La única otra cosa que puedo pensar es que tal vez otro proceso ya esté involucrado en este camino. Tal vez si puedo finalizar este proceso, el CreateFileA podría tener éxito? El enfoque libusb de Roel implica separar el controlador del kernel: https://github.com/roelj/inklingreader/blob/master/src/usb/online-mode.c#L98 

PD En algún lugar leí que si otro proceso ya ha abierto este dispositivo, nuestro abierto tiene que coincidir con los permisos de este abierto anterior. Y también leí que Windows automáticamente abre todos los dispositivos HID al detectarlos.

Descubre qué proceso tiene un bloqueo exclusivo en el mango de un dispositivo USB

PPS tal vez una idea es probar una alternativa HID lib ¿Cuál es la mejor biblioteca de usb para comunicarse con dispositivos usb HID en Windows? 

PPPS tal vez necesito ejecutar mi código como administrador. Pero esa no es una buena solución.


10
2018-05-13 15:13


origen


Respuestas:


He visto un comportamiento similar. El problema ERROR_SHARING_VIOLATION comenzó a ocurrir después de actualizar a Windows 10 Anniversary Edition. El problema solo se ve para los dispositivos USB HID conectados cuando se inicia Windows. Si desenchufa y conecta el dispositivo USB después de que Windows haya comenzado, CreateFile es exitoso. Todavía no he encontrado una causa raíz o una solución.


1
2017-11-21 15:04