Colete informações sobre dispositivos USB suspensos via IOUSBDeviceInterface245
Pergunta
Estou tentando obter algumas informações (como o nome de um produto) por meio do IOUSBDeviceInterface245
(do IOKit no Mac OS X):
Código # 1
io_iterator_t iterator;
io_object_t usb_device
SInt32 score = 0;
kern_return_t kr = IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceNameMatching("AppleUSBOHCI"),
&iterator);
IOCFPlugInInterface **plugin_interface = NULL;
IOUSBDeviceInterface245 **usb_interface = NULL;
// ...
// enumerate devices (usb_device = IOIteratorNext(iterator))
// ...
IOReturn return_code = IOCreatePlugInInterfaceForService(usb_device,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugin_interface,
&score);
HRESULT h_result = (*pluginInterface)->QueryInterface(pluginInterface,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID245),
(LPVOID)&usb_interface);
IODestroyPlugInInterface(pluginInterface);
UInt8 product_string_index;
return_code = (*usb_interface)->USBGetProductStringIndex(usb_interface,
&product_string_index);
// Next, getting a product string by string's index. To do so, we need to send
// IOUSBDevRequest (with type "kUSBRqGetDescriptor") to the current USB-device.
// Code bellow - is a pseudocode:
char *product_name = malloc(128);
get_string_by_index(usb_interface, product_string_index, product_string, 128);
Este código está funcionando bem para todos os dispositivos que funcionam agora, mas não funciona para suspensos ("hibernando")
dispositivos (product_name
é apenas uma string em branco).
Mas, se eu usar este código:
Código # 2
CFMutableDictionaryRef child_properties = CFDictionaryCreateMutable(NULL, 0,
NULL,NULL);
kern_return_t kr;
io_service_t io_service;
// iterator = iterator for "AppleUSBOHCI" or "AppleUSBEHCI" services
while((io_service = IOIteratorNext(iterator))) {
io_iterator_t children_iterator;
kernel_return = IORegistryEntryGetChildIterator(io_service, kIOServicePlane,
&children_iterator);
io_registry_entry_t child;
while((child = IOIteratorNext(children_iterator))) {
// Create a CFDictionary with usb-device's properties
IORegistryEntryCreateCFProperties(child, &child_properties,
kCFAllocatorDefault,
kNilOptions);
NSLog(@"%@",[(NSDictionary*)child_properties valueForKey:@"USB Product Name"]);
}
}
está funcionando para todos os dispositivos (não sei por quê).
Tentei despertar dispositivos suspensos com este código (usando o código # 1):
(*usb_interface)->USBDeviceSuspend(usb_interface, false);
mas não mudou nada.
Uma coisa que notei - o código # 1 está funcionando totalmente para todas as propriedades de dispositivos adormecidos, exceto valores de string (que obtendo por string índice).
ATUALIZAÇÃO:
Portanto, minha pergunta é como posso cancelar a suspensão de um dispositivo para usar com o primeiro bloco de código ?
Obrigado.
Solução
Você não pode ler a string de um dispositivo suspenso (como no código # 1), pois é lida diretamente do dispositivo (que não pode responder, pois está suspenso).Para lê-los diretamente, você precisará cancelar a suspensão do dispositivo primeiro (o que pode ser uma má ideia se ele foi suspenso por um driver, também, lembre-se de verificar o sucesso)
Se você quiser ler as strings padrão, use o segundo bloco de código (que lê as propriedades, que já foram buscadas no dispositivo)