From 782ed343f74b6e44ea23c3e49d556a351cf9150a Mon Sep 17 00:00:00 2001 From: Paul Molloy Date: Sat, 19 Nov 2016 19:10:13 -0600 Subject: [PATCH] modified: source/inlprog.c -moved usb device operations into usb_operations module new file: source/usb_operations.c new file: source/usb_operations.h -creation of usb_operations module -currently handles libusb open/close and retrieving INL retro-prog usb handle. --- host/source/inlprog.c | 148 ++--------------------------- host/source/usb_operations.c | 174 +++++++++++++++++++++++++++++++++++ host/source/usb_operations.h | 38 ++++++++ 3 files changed, 221 insertions(+), 139 deletions(-) create mode 100644 host/source/usb_operations.c create mode 100644 host/source/usb_operations.h diff --git a/host/source/inlprog.c b/host/source/inlprog.c index 56e60e2..289767c 100644 --- a/host/source/inlprog.c +++ b/host/source/inlprog.c @@ -10,6 +10,8 @@ //"make debug" to get DEBUG msgs on entire program #include "dbg.h" +#include "usb_operations.h" + //control transfer request types //uint8_t libusb_control_setup::bmRequestType //Request type. @@ -40,112 +42,14 @@ int main(int argc, char *argv[]) { - int rv = 0; - //context set to NULL since only acting as single user of libusb libusb_context *context = NULL; + libusb_device_handle *rprog_handle = NULL; - debug("Initalizing libusb"); - //initialize libusb must be called prior to any other libusb function - //returns 0 on success LIBUSB_ERROR code on failure - //int libusb_init ( libusb_context ** context) - int usb_init = libusb_init(&context); - check( usb_init == LIBUSB_SUCCESS, "Failed to initialize libusb: %s", libusb_strerror(usb_init)); - - //void libusb_set_debug ( libusb_context * ctx, int level ) - libusb_set_debug(context, LIBUSB_LOG_LEVEL_ERROR); - //LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) - //LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr - //LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr - //LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, - // warning and error messages are printed to stderr - //LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout, - // warnings and errors to stderr - - //discover all usb devices - libusb_device **device_list = NULL; - //ssize_t libusb_get_device_list (libusb_context *ctx, libusb_device ***list) - // Returns a list of USB devices currently attached to the system. - // return value is number of devices plus one as list is null terminated, or LIBUSB_ERROR if negative. - // Must free device list after done with it - ssize_t dev_count = libusb_get_device_list( context, &device_list); - check( dev_count >= 0, "libusb unable to find any devices: %s", libusb_strerror(dev_count)); - - ssize_t i = 0; - - libusb_device *retroprog = NULL; - libusb_device *device = NULL; - struct libusb_device_descriptor desc; - libusb_device_handle *handle = NULL; - unsigned char str[256]; + rprog_handle = open_usb_device( context ); + check_debug(rprog_handle != NULL, "Unable to open INL retro-prog usb device handle."); - debug("searching %d total devices", dev_count-1); - for( i=0; i 0) { - printf("manf_ascii: %s\n",str); - } - } - if (desc.iProduct) { - if ( libusb_get_string_descriptor_ascii( handle, desc.iProduct, str, sizeof(str) ) > 0) { - printf("prod_ascii: %s\n",str); - } - } - if (desc.bcdDevice) { - printf("bcd Device: %d\n",desc.bcdDevice); - //old firmware returns 256, new returns 512 - //USB_CFG_DEVICE_VERSION 0x00, 0x01 for v1.0, 0x00, 0x02 for v2.0 (minor then major) - //v2.0 released late 2016 early 2017 - } - - //TODO verify it's INL Retro Prog by InfiniteNesLives.com, then break - //else close handle and keep searching as there might be other devices with matching prod/devIDs - //also verify firmware version is compatible - // - //TODO verify have permission to interface with device, else give notice to user - - break; - } - } - check( retroprog != NULL, "Could not find INL retro-prog USB device"); - - //free device list now that INL retro-prog was found and opened - //void libusb_free_device_list ( libusb_device ** list, int unref_devices ) - libusb_free_device_list( device_list, 1); //don't completely understand the unref_devices = 1... - device_list = NULL; //denote that device list is free if end up in error - //Guess this is what you're supposed to do.. - // the process of opening a device can be viewed as follows: - // - // Discover devices using libusb_get_device_list(). - // Choose the device that you want to operate, and call libusb_open(). - // Unref all devices in the discovered device list. - // Free the discovered device list. - // - // The order is important - you must not unreference the device before attempting to open it, because unreferencing it may destroy the device. - // - // For convenience, the libusb_free_device_list() function includes a parameter to optionally unreference all the devices in the list before freeing the list itself. This combines steps 3 and 4 above. - // - // As an implementation detail, libusb_open() actually adds a reference to the device in question. This is because the device remains available through the handle via libusb_get_device(). The reference is deleted during libusb_close(). - - - //code and life to axe int xfr_cnt = 0; uint16_t wValue = 0; //setup packet wValue field uint16_t wIndex = 0; //setup packet wIndex field @@ -205,7 +109,7 @@ int main(int argc, char *argv[]) switch (action) { case 'o': //ON send REQ_LED_ON - xfr_cnt = libusb_control_transfer(handle, + xfr_cnt = libusb_control_transfer(rprog_handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, REQ_LED_ON, wValue, wIndex, (unsigned char *)buffer254, sizeof(buffer254), SEC_5); @@ -214,7 +118,7 @@ int main(int argc, char *argv[]) break; case 'f': - xfr_cnt = libusb_control_transfer(handle, + xfr_cnt = libusb_control_transfer(rprog_handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, REQ_LED_OFF, wValue, wIndex, (unsigned char *)buffer254, sizeof(buffer254), SEC_5); @@ -227,46 +131,12 @@ int main(int argc, char *argv[]) exit(1); } - //free device list if it was left open - if (device_list) { - printf("Whoops! freeing device list\n"); - libusb_free_device_list( device_list, 1); - } - - //must close device before exiting - libusb_close(handle); - handle = NULL; //delete handle reference so error won't retry closing - - //deinitialize libusb to be called after closing all devices and before teminating application - libusb_exit(context); - + close_usb( context, rprog_handle); return 0; error: - printf("program went to error\n"); - - if (device_list) { - printf("freeing device list\n"); - libusb_free_device_list( device_list, 1); - } - - if (handle) { - printf("closing usb device\n"); - libusb_close(handle); - } - - if (usb_init == LIBUSB_SUCCESS) { - printf("deinitializing libusb\n"); - libusb_exit(context); - } - - if (rv == LIBUSB_ERROR_ACCESS) { - printf("-------------------------------------------------------\n"); - printf("Denied Permission is expected for initial use on Linux.\n"); - printf("See udev-rule-help/Readme.txt in host dir for help gaining permission.\n"); - printf("Try command with sudo for a cheap temporary solution.\n"); - } + printf("main program went to error\n"); return 1; diff --git a/host/source/usb_operations.c b/host/source/usb_operations.c new file mode 100644 index 0000000..6e7bd38 --- /dev/null +++ b/host/source/usb_operations.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include +#include +#include + +//uncomment to DEBUG this file alone +//#define DEBUG +//"make debug" to get DEBUG msgs on entire program +#include "dbg.h" + +#include "usb_operations.h" + +libusb_device_handle * open_usb_device( libusb_context *context ) +{ + int rv = 0; + + //context set to NULL since only acting as single user of libusb + //libusb_context *context = NULL; + //passed in from main + + debug("Initalizing libusb"); + //initialize libusb must be called prior to any other libusb function + //returns 0 on success LIBUSB_ERROR code on failure + //int libusb_init ( libusb_context ** context) + int usb_init = libusb_init(&context); + check( usb_init == LIBUSB_SUCCESS, "Failed to initialize libusb: %s", libusb_strerror(usb_init)); + + //void libusb_set_debug ( libusb_context * ctx, int level ) + libusb_set_debug(context, LIBUSB_LOG_LEVEL_ERROR); + //LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) + //LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr + //LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr + //LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, + // warning and error messages are printed to stderr + //LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout, + // warnings and errors to stderr + + //discover all usb devices + libusb_device **device_list = NULL; + //ssize_t libusb_get_device_list (libusb_context *ctx, libusb_device ***list) + // Returns a list of USB devices currently attached to the system. + // return value is number of devices plus one as list is null terminated, or LIBUSB_ERROR if negative. + // Must free device list after done with it + ssize_t dev_count = libusb_get_device_list( context, &device_list); + check( dev_count >= 0, "libusb unable to find any devices: %s", libusb_strerror(dev_count)); + + ssize_t i = 0; + + libusb_device *retroprog = NULL; + libusb_device *device = NULL; + struct libusb_device_descriptor desc; + libusb_device_handle *handle = NULL; + unsigned char str[256]; + + + debug("searching %d total devices", dev_count-1); + for( i=0; i 0) { + debug("manf_ascii: %s\n",str); + } + } + if (desc.iProduct) { + if ( libusb_get_string_descriptor_ascii( handle, desc.iProduct, str, sizeof(str) ) > 0) { + debug("prod_ascii: %s\n",str); + } + } + if (desc.bcdDevice) { + debug("bcd Device: %x\n",desc.bcdDevice); + //old firmware returns 256, new returns 512 + //old firmware returns 0x100, new returns 0x200 + //USB_CFG_DEVICE_VERSION 0x00, 0x01 for v1.0, 0x00, 0x02 for v2.0 (minor then major) + //v2.0 released late 2016 + } + + //TODO verify it's INL Retro Prog by InfiniteNesLives.com, then break + //else close handle and keep searching as there might be other devices with matching prod/devIDs + //also verify firmware version is compatible + // + //TODO verify have permission to interface with device, else give notice to user + + break; + } + } + check( retroprog != NULL, "Could not find INL retro-prog USB device"); + + //free device list now that INL retro-prog was found and opened + //void libusb_free_device_list ( libusb_device ** list, int unref_devices ) + libusb_free_device_list( device_list, 1); //don't completely understand the unref_devices = 1... + device_list = NULL; //denote that device list is free if end up in error + //Guess this is what you're supposed to do.. + // the process of opening a device can be viewed as follows: + // + // Discover devices using libusb_get_device_list(). + // Choose the device that you want to operate, and call libusb_open(). + // Unref all devices in the discovered device list. + // Free the discovered device list. + // + // The order is important - you must not unreference the device before attempting to open it, because unreferencing it may destroy the device. + // + // For convenience, the libusb_free_device_list() function includes a parameter to optionally unreference all the devices in the list before freeing the list itself. This combines steps 3 and 4 above. + // + // As an implementation detail, libusb_open() actually adds a reference to the device in question. This is because the device remains available through the handle via libusb_get_device(). The reference is deleted during libusb_close(). + + + //free device list if it was left open + if (device_list) { + printf("Whoops! freeing device list\n"); + libusb_free_device_list( device_list, 1); + } + + return handle; + +error: + printf("open_usb_device went to error\n"); + + if (device_list) { + printf("freeing device list\n"); + libusb_free_device_list( device_list, 1); + } + + if (handle) { + printf("closing usb device\n"); + libusb_close(handle); + } + + if (usb_init == LIBUSB_SUCCESS) { + printf("deinitializing libusb\n"); + libusb_exit(context); + } + + if (rv == LIBUSB_ERROR_ACCESS) { + printf("-------------------------------------------------------\n"); + printf("Denied Permission is expected for initial use on Linux.\n"); + printf("See udev-rule-help/Readme.txt in host dir for help gaining permission.\n"); + printf("Try command with sudo for a cheap temporary solution.\n"); + } + + return NULL; + +} + +void close_usb(libusb_context *context, libusb_device_handle *handle) +{ + + + //must close device before exiting + libusb_close(handle); + handle = NULL; //delete handle reference so error won't retry closing + + //deinitialize libusb to be called after closing all devices and before teminating application + libusb_exit(context); + + + return; +} diff --git a/host/source/usb_operations.h b/host/source/usb_operations.h new file mode 100644 index 0000000..901760c --- /dev/null +++ b/host/source/usb_operations.h @@ -0,0 +1,38 @@ +#ifndef _usb_operations_h +#define _usb_operations_h + +#include "usb_operations.h" + +//control transfer request types +//uint8_t libusb_control_setup::bmRequestType +//Request type. +// Bits 0:4 determine recipient, see libusb_request_recipient. Bits 5:6 determine type, see libusb_request_type. Bit 7 determines data transfer direction, see libusb_endpoint_direction. +// +//libusb_request_types: +//LIBUSB_REQUEST_TYPE_STANDARD Standard handled by driver during setup/etc +//LIBUSB_REQUEST_TYPE_CLASS Class for use with specific device classes like HID. +//LIBUSB_REQUEST_TYPE_VENDOR Vendor application specific as we choose which is what we'll be utilizing for all transfers +//LIBUSB_REQUEST_TYPE_RESERVED Reserved. +// +//libusb_request_recipients: +//LIBUSB_RECIPIENT_DEVICE Device. +//LIBUSB_RECIPIENT_INTERFACE Interface. +//LIBUSB_RECIPIENT_ENDPOINT Endpoint. +//LIBUSB_RECIPIENT_OTHER Other. +// +//LIBUSB_ENDPOINT_IN In: device-to-host. +//LIBUSB_ENDPOINT_OUT Out: host-to-device. + +// vendor requests also defined in firmware +// TODO put in combined .h file for both host and fw +#define REQ_LED_ON 1 +#define REQ_LED_OFF 2 + +//USB timeout +#define SEC_5 5000 + +libusb_device_handle * open_usb_device( libusb_context *context ); + +void close_usb(libusb_context *context, libusb_device_handle *handle); + +#endif