diff --git a/Software/.gitignore b/Software/.gitignore new file mode 100644 index 0000000..1746e32 --- /dev/null +++ b/Software/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/Software/Makefile b/Software/Makefile new file mode 100644 index 0000000..b02e953 --- /dev/null +++ b/Software/Makefile @@ -0,0 +1,56 @@ +BIN = bin +OBJ = obj +SRC = src +INCLUDE = include +CFLAGS = +CLIBS = -lusb-1.0 -I"C:\Program Files\zLib\libusb-1.0.23\include" +#sur le Windows d'Axel : +CLIBS := ${CLIBS} -B"C:\Program Files\zLib\libusb-1.0.23\MinGW32\static" +GNUMAKEFLAGS = --no-print-directory + +gcc = gcc +#sur le Windows d'Axel : +gcc := "/mnt/c/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/bin/gcc.exe" + + +DEBUG?=0 +ifeq ($(DEBUG), 0) + CFLAGS = -W -Wall +else + CFLAGS = -W -Wall -g -O0 -DDEBUG +endif + + + +all : main + + +version : + ${gcc} -v + +main : bin libusb_wrapper ${SRC}/main.c + ${gcc} -o ${OBJ}/$@.o -c ${SRC}/$@.c -I ${INCLUDE} ${CLIBS} ${CFLAGS} + ${gcc} -o ${BIN}/$@.exe ${OBJ}/main.o ${OBJ}/libusb_wrapper.o ${CFLAGS} ${CLIBS} + +demostep : main + ${BIN}/main.exe demo4.1 + +libs: libusb_wrapper + +libusb_wrapper: obj ${SRC}/libusb_wrapper.c ${INCLUDE}/libusb_wrapper.h + ${gcc} -o ${OBJ}/$@.o -c ${SRC}/$@.c -I ${INCLUDE} ${CLIBS} ${CFLAGS} + + + +obj : + @-mkdir ${OBJ} + +bin : + @-mkdir ${BIN} + +clean : + rm -rf obj/*.o + +mrproper: clean + rm -rf bin + rm -rf obj diff --git a/Software/hexToDec.sh b/Software/hexToDec.sh new file mode 100644 index 0000000..a01673d --- /dev/null +++ b/Software/hexToDec.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ $# -eq 1 ]; then + echo "obase=10; ibase=16; $1" | bc +else + echo "Type a hex number" + read hexNum + echo -n "The decimal value of $hexNum=" + echo "obase=10; ibase=16; $hexNum" | bc +fi diff --git a/Software/include/libusb_wrapper.h b/Software/include/libusb_wrapper.h new file mode 100644 index 0000000..dde7201 --- /dev/null +++ b/Software/include/libusb_wrapper.h @@ -0,0 +1,35 @@ +#ifndef LIBUSB_WRAPPER_H_ +#define LIBUSB_WRAPPER_H_ + +#include +#include +#include +#include + +void usbinit(libusb_context **context_ptr); +void usbclose(libusb_context *context); + +void interfaceclaim(libusb_device_handle *handle, + struct libusb_interface *interface); +void interfaceclose(libusb_device_handle *handle, + struct libusb_interface *interface); + +ssize_t getListDevices(libusb_context *context, libusb_device ***list_ptr); +void getFromKernel(libusb_device_handle *handle, int interface); + +void displayDevices(libusb_context *context); +void displayDevicesMore(libusb_context *context); + +void getFirstDeviceFromID(libusb_context *context, int vid, int pid, + libusb_device **device); + +void getOurInterfaces(libusb_device *device, + struct libusb_interface **int_hidjoy, + struct libusb_interface **int_leds, + struct libusb_interface **int_vibrators); + +void displayDeviceEndpoints(); + +char getOnlyEndpoint(struct libusb_interface *interface); + +#endif diff --git a/Software/src/libusb_wrapper.c b/Software/src/libusb_wrapper.c new file mode 100644 index 0000000..45b8717 --- /dev/null +++ b/Software/src/libusb_wrapper.c @@ -0,0 +1,307 @@ +#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 + + if (interface_desc->bInterfaceClass == + LIBUSB_CLASS_VENDOR_SPEC) { // ON PEUT VERIFIER LA CLASS + printf("> vendor specific class\n"); + + 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 + for (int indexInterface = 0; indexInterface < config->bNumInterfaces; + indexInterface++) { + + const struct libusb_interface *interface = + &config->interface[indexInterface]; + + // todo use le descriptor pour avoir bInterfaceNumber? + if (indexInterface == 0) { + *int_hidjoy = (struct libusb_interface *)interface; + } else if (indexInterface == 1) { + *int_leds = (struct libusb_interface *)interface; + } else if (indexInterface == 2) { + *int_vibrators = (struct libusb_interface *)interface; + } + + //#define pour les indices correspondants aux interfaces + // variables globales + } +} + +char getOnlyEndpoint(struct libusb_interface *interface) { + + const struct libusb_interface_descriptor *interface_desc = + &interface->altsetting[0]; + + const struct libusb_endpoint_descriptor *endpoint_desc = + &interface_desc->endpoint[0]; + + if (endpoint_desc->bmAttributes != + LIBUSB_TRANSFER_TYPE_INTERRUPT) // ON PEUT VERIFIER LE TRANSFER TYPE + printf("> is NOT of type INTERRUPT\n"); + + return (char)endpoint_desc->bEndpointAddress; +} diff --git a/Software/src/main.c b/Software/src/main.c new file mode 100644 index 0000000..b78130b --- /dev/null +++ b/Software/src/main.c @@ -0,0 +1,132 @@ +#include "libusb_wrapper.h" +#include +#include + +#define VID 1003 +#define PID 8259 + +int main(int argc, char *argv[]) { + printf("Hello World :-|\n"); + + libusb_context *context; + usbinit(&context); +#ifdef DEBUG + libusb_set_option(context, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG); +#endif + + if (argc > 1) { + // command mode + if (strcmp(argv[1], "demo4.1") == 0) { // if 4.1 + printf("\e[91mDemo 4.1\e[39m\n"); + displayDevices(context); + } else if (strcmp(argv[1], "demo4.1plus") == 0) { // if 4.1 bonus + printf("\e[91mDemo 4.1\e[39m\n"); + displayDevicesMore(context); + } else if (strcmp(argv[1], "demo4.2") == 0) { // if 4.2 + printf("\e[91mDemo 4.2\e[39m\n"); + + if (argc > 3) { + uint16_t vendor_id; + uint16_t product_id; + sscanf(argv[2], "%hu", &vendor_id); + sscanf(argv[3], "%hu", &product_id); + + libusb_device_handle *handle; + handle = + libusb_open_device_with_vid_pid(context, vendor_id, product_id); + if (handle != NULL) { + printf("Show endpoints of VID:%hu;PID:%hu\n", vendor_id, product_id); + displayDeviceEndpoints(handle); + } else { + printf("Error while getting handle of VID:%hu;PID:%hu\n", vendor_id, + product_id); + } + } else { + printf("Error, need VID and PID\n"); + } + } else { + printf("Wrong command\n"); + } + + } else { + // interactive mode + printf("Welcome to interactive mode\n"); + printf("Compiled for VID:PID => %d:%d\n", VID, PID); + + // Find the device + printf("Iterate list of devices, and getting the right one\n"); + libusb_device *device = NULL; + getFirstDeviceFromID(context, VID, PID, &device); + // code + if (device == NULL) { + printf("Error : cannot find the device !\n"); + return 1; + } + + // take the handle + libusb_device_handle *device_handle = NULL; + if (libusb_open(device, &device_handle) != 0) { + printf("Error : cannot handle the device\n"); + return 1; + } + + // Take the interfaces + printf("\nSearch for interfaces\n"); + struct libusb_interface *int_hidjoy = NULL; + struct libusb_interface *int_leds = NULL; + struct libusb_interface *int_vibrators = NULL; + getOurInterfaces(device, &int_hidjoy, &int_leds, &int_vibrators); + + // Claim interface + printf("\nClaim interfaces ...\n"); + printf("-Leds\n"); + interfaceclaim(device_handle, int_leds); + printf("-Vibrators\n"); + interfaceclaim(device_handle, int_vibrators); + + // récupération des endpoints + printf("\nRécupération endpoints\n"); + printf("-Leds"); + int endpoint_leds = + getOnlyEndpoint(int_leds); /* ID of endpoint (bit 8 is 0) */ + printf(" is %d\n", endpoint_leds); + printf("-Vibrators"); + int endpoint_vibrators = + getOnlyEndpoint(int_vibrators); /* ID of endpoint (bit 8 is 0) */ + printf(" is %d\n", endpoint_vibrators); + + /*LE CODE UTILE*/ + int i; + for(i = 0 ; i<5 ; i++) { + unsigned char data[2] = {0xff, 0xff}; // data to send or to receive + int size = 2; // size to send or maximum size to receive + int timeout = 1000; // timeout in ms + + // OUT interrupt, from host to device + int bytes_out; + printf("%p %02X\n", device_handle, endpoint_leds); + int status = libusb_interrupt_transfer(device_handle, endpoint_leds, data, + size, &bytes_out, timeout); + if (status != 0) { + perror("libusb_interrupt_transfer"); + exit(-1); + } + + //sleep(1); demande l'ajout de macro pour la portabilité + } + /*FIN DU CODE UTILE*/ + + // Close + printf("\nUnclaim interfaces ...\n"); + printf("-Leds\n"); + interfaceclose(device_handle, int_leds); + printf("-Vibrators\n"); + interfaceclose(device_handle, int_vibrators); + + printf("Finished\n"); + } + + usbclose(context); + + return 0; +} -- libgit2 0.21.2