detectPrinterConfiguration method
Implementation
Future<Map<String, dynamic>> detectPrinterConfiguration(
int vendorId, int productId) async {
final Pointer<libusb_device_handle>? handleNullable =
openDevice(vendorId, productId);
if (handleNullable == nullptr || handleNullable == null) {
return {'success': false, 'error': 'No se pudo abrir el dispositivo'};
}
// Una vez verificado que no es nulo, lo asignamos a una variable no nullable
final handle = handleNullable;
try {
// Obtener el dispositivo a partir del handle
final device = _bindings.libusb_get_device(handle);
// Obtener el descriptor del dispositivo
final deviceDescriptor = calloc<libusb_device_descriptor>();
final descResult =
_bindings.libusb_get_device_descriptor(device, deviceDescriptor);
if (descResult < 0) {
calloc.free(deviceDescriptor);
return {
'success': false,
'error': 'No se pudo obtener el descriptor del dispositivo',
'errorCode': descResult
};
}
// Obtener información de configuración
final configDescPtr = calloc<Pointer<libusb_config_descriptor>>();
final configResult =
_bindings.libusb_get_active_config_descriptor(device, configDescPtr);
if (configResult < 0) {
calloc.free(deviceDescriptor);
calloc.free(configDescPtr);
return {
'success': false,
'error': 'No se pudo obtener el descriptor de configuración',
'errorCode': configResult
};
}
final config = configDescPtr.value;
final numInterfaces = config.ref.bNumInterfaces;
// Información básica del dispositivo
Map<String, dynamic> deviceInfo = {
'vendorId': deviceDescriptor.ref.idVendor,
'productId': deviceDescriptor.ref.idProduct,
'deviceClass': deviceDescriptor.ref.bDeviceClass,
'deviceSubClass': deviceDescriptor.ref.bDeviceSubClass,
'deviceProtocol': deviceDescriptor.ref.bDeviceProtocol,
'busNumber': _bindings.libusb_get_bus_number(device),
'deviceAddress': _bindings.libusb_get_device_address(device),
'numInterfaces': numInterfaces,
'interfaces': <Map<String, dynamic>>[]
};
// Probar a reclamar interfaces y detectar endpoints manualmente
for (int i = 0; i < numInterfaces; i++) {
// Primero desconectamos el driver del kernel si es necesario
if (Platform.isLinux || Platform.isMacOS) {
try {
final hasKernelDriver =
_bindings.libusb_kernel_driver_active(handle, i);
if (hasKernelDriver == 1) {
_bindings.libusb_detach_kernel_driver(handle, i);
}
} catch (e) {
log("Error al verificar/desconectar driver del kernel para interfaz $i: $e");
}
}
// Intentar reclamar la interfaz
int claimResult = _bindings.libusb_claim_interface(handle, i);
if (claimResult < 0) {
log("No se pudo reclamar la interfaz $i: $claimResult");
continue;
}
// Crear una estructura para guardar la información de la interfaz
Map<String, dynamic> interfaceInfo = {
'number': i,
'canClaim': true,
'endpoints': <Map<String, dynamic>>[]
};
// Probar endpoints comunes para impresoras
List<int> commonEndpoints = [0x01, 0x02, 0x03, 0x81, 0x82, 0x83];
for (int epAddress in commonEndpoints) {
// Para simplificar, asumimos que todos los endpoints son de tipo bulk
bool isOutput = (epAddress & 0x80) ==
0; // Si el bit más significativo es 0, es de salida
// Para detectar si un endpoint funciona, podríamos intentar una transferencia de prueba
// Pero esto podría causar efectos no deseados, así que solo reportamos la dirección
interfaceInfo['endpoints'].add({
'address': epAddress,
'type': 'bulk', // Asumimos tipo bulk para impresoras
'direction': isOutput ? 'output' : 'input'
});
}
// Liberar la interfaz
_bindings.libusb_release_interface(handle, i);
// Reconectar el driver del kernel si es necesario
if (Platform.isLinux || Platform.isMacOS) {
try {
final hasKernelDriver =
_bindings.libusb_kernel_driver_active(handle, i);
if (hasKernelDriver == 1) {
_bindings.libusb_attach_kernel_driver(handle, i);
}
} catch (e) {
log("Error al reconectar driver del kernel para interfaz $i: $e");
}
}
deviceInfo['interfaces'].add(interfaceInfo);
}
// Liberar recursos
_bindings.libusb_free_config_descriptor(config);
calloc.free(configDescPtr);
calloc.free(deviceDescriptor);
return {
'success': true,
'deviceInfo': deviceInfo,
'note':
'Los endpoints listados son endpoints comunes para impresoras y pueden no corresponder exactamente a los endpoints reales del dispositivo.'
};
} catch (e) {
return {
'success': false,
'error': 'Error al detectar configuración',
'exception': e.toString()
};
} finally {
closeDevice(handle);
}
}