J'utilise stack overflow depuis longtemps maintenant, et pour la plupart des problèmes, une solution est déjà disponible. C'est la première fois que je n'arrive pas à trouver une solution avec le web. J'espère que quelqu'un a la réponse au problème suivant.
Introduction Je travaille actuellement sur un projet qui devrait être capable d'exécuter une commande et d'agir en fonction de sa réponse. Ce projet tourne sur un système debian dans une application console c++. Afin de pouvoir exécuter de telles commandes, j'ai essayé d'utiliser la commande LibUSB bibliothèque.
Le problème Chaque fois que des paquets sont envoyés, il ne renvoie pas de réponse valide telle que décrite dans la documentation du matériel. Un outil par défaut est disponible qui déclenche une commande de calibration, j'ai reniflé ces paquets avec Wireshark Mais la structure des appels d'interruption OUT de l'outil de callibration diffère de celle générée par LibUSB, ce qui (je pense) fait que la commande n'est pas exécutée.
La documentation fournit l'une des commandes suivantes, qui devrait exécuter un contrôle de diagnostic renvoyant 5 octets de données.
[0] Header: 0x02
[1] Command: 0x4C
[2] Byte to send: 0x02 (N bytes to send, Argument + data size)
[3] Argument: 0x09
[4] Data: 0x00
La réponse doit avoir le format suivant :
[0] Header: 0x02
[1] Command: 0x4C
[2] Byte to send: 0x03 (N bytes to send, Argument + data size)
[3] Argument: 0x09
[4] Processing result: D-1
[5] Diagnostic result: D-2
D-1 soit 0x01 : Normal ou 0x00 Erreur D-2 soit 0x00 : normal ou non 0x00, code d'erreur lié.
Ce qui a été essayé jusqu'à présent
-
Types de transfert :
- Synchrone :
- Libusb_bulk_transfer
- Libusb_control_transfer
- libusb_interrupt_transfer
- Asynchrone :
- Libusb_fill_bulk_transfer
- Libusb_fill_control_transferts
- Libusb_fill_interrupt_transfer
J'ai essayé les deux implémentations, asynchrone et synchrone, de la bibliothèque LibUSB. Pour le transfert de contrôle, j'ai essayé de changer aléatoirement les variables après que les moyens les plus logiques de les remplir aient été épuisés, sans succès, comme on pouvait s'y attendre. Puisque les résultats trouvés dans le reniflage de paquets indiquaient clairement que des appels INTERRUPT étaient effectués.
Interfaces : Le matériel possède deux interfaces. L'interface 0 qui contient OUT 0x02 et IN 0x81, et l'interface 1 qui contient OUT 0x04 et IN 0x83. Le reniflage de l'appel d'interruption USB vers le dispositif déclenché par l'outil a permis d'établir que l'interface 1 était utilisée pour la commande de diagnostic. (J'ai également essayé l'interface 0 avec IN et OUT, mais cela n'a pas fonctionné.
Reniflage de paquets avec Wireshark
Résultats du reniflage de paquets Requêtes et réponses générées par l'outil : IMG : Interruption OUT (J'ai marqué le passage où la commande est effectivement fournie) IMG : Interruption IN response Ce code fonctionne réellement et renvoie l'ensemble de données attendu dans son emplacement de données. (comme décrit ci-dessus, le format de retour est correct, 0x01 et 0x00).
Requête et réponse générées avec le code d'utilisation de LibUSB : IMG : Interruption OUT IMG : Interruption IN réponse
Oui, j'ai également essayé de régler la mémoire tampon sur une taille de 64, la taille maximale de la mémoire tampon pour le matériel. Malheureusement, cela n'a pas fonctionné. Comme on le voit clairement, les deux demandes sont très différentes, est-ce que j'utilise la mauvaise méthode de transfert ? Existe-t-il un autre format supporté dans lequel vous pouvez envoyer des commandes ?
Extrait de code utilisé : L'extrait de code est un peu dépassé, j'ai essayé de le réécrire/éditer plusieurs fois, les dernières implémentations ayant été utilisées à partir d'exemples en ligne.
#define USB_VENDOR_ID <VENDOR_ID>/* USB vendor ID used by the device
* 0x0483 is STMs ID
*/
#define USB_PRODUCT_ID <PRODUCT_ID> /* USB product ID used by the device */
#define USB_ENDPOINT_IN (LIBUSB_ENDPOINT_IN | 0x83) /* endpoint address */
#define USB_ENDPOINT_OUT (LIBUSB_ENDPOINT_OUT | 0x04) /* endpoint address */
#define USB_TIMEOUT 3000 /* Connection timeout (in ms) */
#define INTERFACE_NO 1
static libusb_context *ctx = NULL;
static libusb_device_handle *handle;
static uint8_t receiveBuf[64];
uint8_t transferBuf[64];
uint16_t counter=0;
int main(int argc, char **argv) {
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_device_handle *dev_handle; //a device handle
libusb_context *ctx = NULL; //a libusb session
int r; //for return values
ssize_t cnt; //holding number of devices in list
r = libusb_init(&ctx); //initialize the library for the session we just declared
if(r < 0) {
qDebug()<<"Init Error "<<r<<endl; //there was an error
return 1;
}
libusb_set_debug(ctx, 4); //set verbosity level to 3, as suggested in the documentation
cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
if(cnt < 0) {
qDebug()<<"Get Device Error"<<endl; //there was an error
return 1;
}
qDebug()<<cnt<<" Devices in list."<<endl;
dev_handle = libusb_open_device_with_vid_pid(ctx, 0x0AFA, 0x7D3); //these are vendorID and productID I found for my usb device
if(dev_handle == NULL)
qDebug()<<"Cannot open device"<<endl;
else
qDebug()<<"Device Opened"<<endl;
libusb_free_device_list(devs, 1); //free the list, unref the devices in it
unsigned char *data = new unsigned char[5] { 0x02, 0x4C, 0x02, 0x09, 0 }; //data to write
data[0]= 0x02;data[1]= 0x4C;data[2]=0x02;data[3]=0x09; data[4]= 0; //some dummy values
int actual; //used to find out how many bytes were written
if(libusb_kernel_driver_active(dev_handle, INTERFACE_NO) == 1) { //find out if kernel driver is attached
qDebug()<<"Kernel Driver Active"<<endl;
if(libusb_detach_kernel_driver(dev_handle, INTERFACE_NO) == 0) //detach it
qDebug()<<"Kernel Driver Detached!"<<endl;
}
r = libusb_claim_interface(dev_handle, INTERFACE_NO); //claim interface 0 (the first) of device (mine had jsut 1)
if(r < 0) {
qDebug()<<"Cannot Claim Interface"<<endl;
return 1;
}
qDebug()<<"Claimed Interface"<<endl;
for(int i = 0; i != sizeof(data); i++) {
fprintf(stderr, "[%d] - %02x\n", i, data[i]);
}
qDebug()<<"Writing Data..."<<endl;
r = libusb_bulk_transfer(dev_handle, (USB_ENDPOINT_OUT | LIBUSB_ENDPOINT_OUT), data, sizeof(data), &actual, 0); //my device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
if(r == 0 && actual == sizeof(data)) //we wrote the 4 bytes successfully
qDebug()<<"Writing Successful!"<<endl;
else
qDebug()<<"Write Error"<<endl;
fprintf(stderr, "Error Writing: %s", libusb_strerror(static_cast<libusb_error>(r)));
r = libusb_release_interface(dev_handle, INTERFACE_NO); //release the claimed interface
if(r!=0) {
qDebug()<<"Cannot Release Interface"<<endl;
return 1;
}
qDebug()<<"Released Interface"<<endl;
libusb_close(dev_handle); //close the device we opened
libusb_exit(ctx); //needs to be called to end the
delete[] data; //delete the allocated memory for data
return 0;
}
J'espère que quelqu'un est capable et désireux de m'aider, car cela fait trois jours que je travaille sur ce sujet et je n'ai toujours pas trouvé de solution logique à ce problème.
Merci d'avance !
~ Mark