libusb_wrapper.c 9.18 KB
#include "libusb_wrapper.h"



void usbinit(libusb_context **context_ptr) {
    //libusb_context *context;
    int statusInit = libusb_init(context_ptr);
    if (statusInit != LIBUSB_SUCCESS) {
        perror("libusb_init");
        exit(-1);
    }
}

void usbclose(libusb_context *context) {
    libusb_exit(context);
}

void interfaceclaim(libusb_device_handle *handle, struct libusb_interface *interface){
    const struct libusb_interface_descriptor * interface_desc = &interface->altsetting[0]; //TODO enlever cette ligne, refactor
    int status=libusb_claim_interface(handle, interface_desc->bInterfaceNumber);
    if(status!=0){ perror("libusb_claim_interface"); exit(-1); }
}

void interfaceclose(libusb_device_handle *handle, struct libusb_interface *interface){
    const struct libusb_interface_descriptor * interface_desc = &interface->altsetting[0];
    int status = libusb_release_interface(handle, interface_desc->bInterfaceNumber);
    if(status!=0){ perror("libusb_release_interface"); exit(-1); }
}

// Si le méchant noyau est passé avant vous :
void getFromKernel(libusb_device_handle *handle, int interface) { //private method for now
    if (libusb_kernel_driver_active(handle, interface)) {
        int statusKDriver = libusb_detach_kernel_driver(handle, interface);
        if (statusKDriver != LIBUSB_SUCCESS) {
            perror("libusb_detach_kernel_driver");
            exit(-1);
        }
    }
}

ssize_t getListDevices(libusb_context *context, libusb_device ***list_ptr) {
    ssize_t count = libusb_get_device_list(context, list_ptr);
    if (count < 0) {
        perror("libusb_get_device_list");
        exit(-1);
    }
    return count;
}

void* _enumerateDevices(libusb_context *context, void (*func)(libusb_device *device)){
    libusb_device **list;
    ssize_t count = getListDevices(context, &list);

    ssize_t i = 0;
    for (i = 0; i < count; i++) {
        libusb_device *device = list[i];

        func(device);
    }

    libusb_free_device_list(list, 1);

    return NULL; //DBGONLY TEMP
}

//print readable string, not asked for tutoring
void _printConfig(libusb_device *device) {//private method
    // Ouverture du périphérique
    libusb_device_handle *handle;
    int statusDevice = libusb_open(device, &handle);
    if (statusDevice != LIBUSB_SUCCESS) {
        perror("libusb_open");
        //return; //exit(-1);
    }

    int MAXLEN_DESCRIPTOR_STRING = 200;
    uint8_t desc_idx = 2;
    //uint16_t langid = 16;
    unsigned char data[200];

    // TEST 16
    for (desc_idx = 0; desc_idx < 16; desc_idx++) {
        int statusAscii = libusb_get_string_descriptor_ascii(
                handle, desc_idx, data, MAXLEN_DESCRIPTOR_STRING);
        if (statusAscii == -9) // TEST seems to be LIBUSB_ERROR
            break;
        printf(" - Descriptor string : %s ; %i\n", data, statusAscii);
    }

    libusb_close(handle);
}


void _displayOneDevice(libusb_device *device){
    struct libusb_device_descriptor desc;

    int status = libusb_get_device_descriptor(device, &desc);
    if (status != LIBUSB_SUCCESS){
        printf("Cannot get device desc : %s\n", libusb_error_name(status)); //DBGONLY
        perror("libusb_open");
        return;
    }

    uint8_t bus = libusb_get_bus_number(device);
    uint8_t address = libusb_get_device_address(device);

    printf("Device Found @ (Bus:Address) %d:%d\n", bus, address);
    printf("Vendor ID 0x0%x\n", desc.idVendor);
    printf("Product ID 0x0%x\n", desc.idProduct);

    //displayDeviceEndpoints(device); //Not really work on Axel@Alptop
}

void displayDevices(libusb_context *context) {
    _enumerateDevices(context, _displayOneDevice);
}

void _displayOneDeviceMore(libusb_device *device){
    _displayOneDevice(device);
    _printConfig(device);
}

void displayDevicesMore(libusb_context *context) {
    _enumerateDevices(context, _displayOneDeviceMore);
}

//get device from iteration (and not from not recommanded function :
//ugly using global vars ?? Cannot communicate between getFirstDeviceFromID and _getFirstDeviceFromID
int g_vid;
int g_pid;
libusb_device *g_device = NULL;
void _getFirstDeviceFromID(libusb_device *device) {
    struct libusb_device_descriptor desc;

    int status = libusb_get_device_descriptor(device, &desc);
    if (status != LIBUSB_SUCCESS){
        printf("Cannot get device desc : %s\n", libusb_error_name(status)); //DBGONLY
        perror("libusb_open");
        return;
    }


    if(desc.idVendor == g_vid && desc.idProduct == g_pid){
        g_device = device;
    }
}

void getFirstDeviceFromID(libusb_context *context, int vid, int pid, libusb_device **device) {
    g_vid = vid; //pass parameters for enumeration
    g_pid = pid; //idem
    _enumerateDevices(context, _getFirstDeviceFromID);
    *device = g_device; //get return from enumeration
}

//void getDevicesFromID(vid, pid) //return array


void displayDeviceEndpoints(libusb_device_handle* handle) {
    //recover pointer from handle
    libusb_device *device;
    device = libusb_get_device(handle);


    // lectures des configs => on prend la première configuration pour l'instant
    /*int configuration = 0; // valueof("bConfigurationValue");
    int statusConfig = libusb_set_configuration(handle, configuration);
    if (statusConfig != LIBUSB_SUCCESS) {
        perror("libusb_set_configuration");
        return;
    }*/

    // 4.2 configuration du périph usb
    struct libusb_config_descriptor *config;
    int statusFetchConfig = libusb_get_active_config_descriptor(device, &config);
    if (statusFetchConfig != LIBUSB_SUCCESS) {
        perror("libusb_get_active_config_descriptor");
        return;
    }

    //caractéristiques globales
    printf("Config.bConfigurationValue : %d\n", config->bConfigurationValue);
    printf("Config/ bLength:%d\nbDescriptorType:%d\nbNumInterfaces:%d\n",
           config->bLength, config->bDescriptorType, config->bNumInterfaces);


    //itération des interfaces
    printf("Itération de l'interface\n");
    for (int indexInterface = 0; indexInterface < config->bNumInterfaces; indexInterface++) {
        printf("-indexInterface=%d\n", indexInterface);
        printf("-Altsetting=%d\n", config->interface[indexInterface].num_altsetting);

        const struct libusb_interface * interface = &config->interface[indexInterface];


        //if 1 setting (or more)
        if(interface->num_altsetting != 0) {
            const struct libusb_interface_descriptor * interface_desc = &interface->altsetting[0];

            printf("--bNumEndpoints=%d\n", interface_desc->bNumEndpoints);
            printf("--bDescriptorType=%d\n", interface_desc->bDescriptorType);

            for(int indexEndpoints = 0; indexEndpoints < interface_desc->bNumEndpoints ; indexEndpoints++){
                const struct libusb_endpoint_descriptor * endpoint_desc = &interface_desc->endpoint[indexEndpoints];
                printf("---bDescriptorType=%d\n", endpoint_desc->bDescriptorType);
                printf("---bEndpointAddress=%d\n", endpoint_desc->bEndpointAddress);

                if(endpoint_desc->extra != NULL)
                    printf("---extra: %s\n", endpoint_desc->extra);
                if(endpoint_desc->bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT)//TODO AJOUT MASQUE ? (voir doc)
                    printf("---is of type INTERRUPT\n");
            }
        }



        //Affichez l’indice et le numéro de chaque interface détectée et réclamée. Affichez aussi les points d’accès trouvés en précisant ceux sauvés.

/*
        //int interface=valueof("bInterfaceNumber");
        int status=libusb_claim_interface(handle,interface->bInterfaceNumber);
        if(status!=0){ perror("libusb_claim_interface"); exit(-1); }

        status=libusb_release_interface(handle,interface->bInterfaceNumber);
        if(status!=0){ perror("libusb_release_interface"); exit(-1); }

        //claim_interface(.., config interface altsetting bInterfaceNumber
        //config interface altsetting endpoint bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT
        //add des enpoint unint8_t*/


        //DESCRIPTOR.C /.H :décommenter


        //IL FAUT RELEASE UNIQUEMENT LES INTERFACES QUI NE SONT PAS DES HID
    }

    printf("\n");

    libusb_close(handle);

}

void getOurInterfaces(libusb_device *device,
                      struct libusb_interface **int_hidjoy,
                      struct libusb_interface **int_leds,
                      struct libusb_interface **int_vibrators
) {
    struct libusb_config_descriptor *config;
    int statusFetchConfig = libusb_get_active_config_descriptor(device, &config);
    if (statusFetchConfig != LIBUSB_SUCCESS) {
        perror("libusb_get_active_config_descriptor");
        return;
    }
    
    //itération des interfaces
    printf("Itération de l'interface\n");
    for (int indexInterface = 0; indexInterface < config->bNumInterfaces; indexInterface++) {

        struct libusb_interface * interface = &config->interface[indexInterface];

        //todo use le descriptor pour avoir bInterfaceNumber?
        if(indexInterface==0){
            *int_hidjoy = interface;
        }else if(indexInterface==1){
            *int_leds = interface;
        }else if(indexInterface==2){
            *int_vibrators = interface;
        }

        //#define pour les indices correspondants aux interfaces
        //variables globales
    }

}