Fnuk. I managed to do a git add -u, when having other dirty bits in the tree. Disregard this one. I'll send a new one.
//Anton On 18 September, 2016 - Anton Lundin wrote: > This adds a simple cp2130 userspace driver. Its probably unusable in the > real world but its a great base to build upon. > > Signed-off-by: Anton Lundin <gla...@acc.umu.se> > --- > CMakeLists.txt | 1 + > android/res/xml/device_filter.xml | 3 + > core/CMakeLists.txt | 7 + > core/libdivecomputer.c | 4 + > core/libdivecomputer.h | 1 + > core/serial_cp2130.c | 283 > ++++++++++++++++++++++++++++++++++++++ > packaging/android/build.sh | 2 +- > scripts/build.sh | 13 +- > 8 files changed, 310 insertions(+), 4 deletions(-) > create mode 100644 core/serial_cp2130.c > > diff --git a/CMakeLists.txt b/CMakeLists.txt > index 095160c..104c323 100644 > --- a/CMakeLists.txt > +++ b/CMakeLists.txt > @@ -33,6 +33,7 @@ option(NO_USERMANUAL "don't include a viewer for the user > manual" OFF) > option(FBSUPPORT "allow posting to Facebook" ON) > option(BTSUPPORT "enable support for QtBluetooth (requires Qt5.4 or newer)" > ON) > option(FTDISUPPORT "enable support for libftdi based serial" OFF) > +option(CP2130SUPPORT "enable support for cp2130 based serial" OFF) > > # Options regarding What should we build on subsurface > option(MAKE_TESTS "Make the tests" ON) > diff --git a/android/res/xml/device_filter.xml > b/android/res/xml/device_filter.xml > index fc9333b..19e535e 100644 > --- a/android/res/xml/device_filter.xml > +++ b/android/res/xml/device_filter.xml > @@ -11,4 +11,7 @@ > <usb-device vendor-id="1027" product-id="63104"/> > <!-- Cressi (Leonardo) Custom PID --> > <usb-device vendor-id="1027" product-id="63104"/> > + > + <!-- CP2130 Chip --> > + <usb-device vendor-id="4292" product-id="34720"/> > </resources> > diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt > index 5c22e23..dff8361 100644 > --- a/core/CMakeLists.txt > +++ b/core/CMakeLists.txt > @@ -18,6 +18,12 @@ if(FTDISUPPORT) > set(SERIAL_FTDI serial_ftdi.c) > endif() > > +if(CP2130SUPPORT) > + message(STATUS "building with cp2130 support") > + add_definitions(-DSERIAL_CP2130) > + set(SERIAL_CP2130 serial_cp2130.c) > +endif() > + > if(BTSUPPORT) > add_definitions(-DBT_SUPPORT) > set(BT_SRC_FILES desktop-widgets/btdeviceselectiondialog.cpp) > @@ -89,6 +95,7 @@ set(SUBSURFACE_CORE_LIB_SRCS > subsurface-qt/CylinderObjectHelper.cpp > subsurface-qt/SettingsObjectWrapper.cpp > ${SERIAL_FTDI} > + ${SERIAL_CP2130} > ${PLATFORM_SRC} > ${BT_CORE_SRC_FILES} > ) > diff --git a/core/libdivecomputer.c b/core/libdivecomputer.c > index cd1b69b..f76a654 100644 > --- a/core/libdivecomputer.c > +++ b/core/libdivecomputer.c > @@ -1034,6 +1034,10 @@ const char *do_libdivecomputer_import(device_data_t > *data) > } else if (!strcmp(data->devname, "ftdi")) { > rc = dc_context_set_custom_serial(data->context, > &serial_ftdi_ops); > #endif > +#ifdef SERIAL_CP2130 > + } else if (!strcmp(data->devname, "cp2130")) { > + rc = dc_context_set_custom_serial(data->context, > &cp2130_serial_ops); > +#endif > } > > if (rc != DC_STATUS_SUCCESS) { > diff --git a/core/libdivecomputer.h b/core/libdivecomputer.h > index f2894b0..8a91fcf 100644 > --- a/core/libdivecomputer.h > +++ b/core/libdivecomputer.h > @@ -65,6 +65,7 @@ extern char *dumpfile_name; > // Thats why I've worked around it with a stupid helper returning it. > dc_custom_serial_t* get_qt_serial_ops(); > extern dc_custom_serial_t serial_ftdi_ops; > +extern dc_custom_serial_t cp2130_serial_ops; > #endif > > #ifdef __cplusplus > diff --git a/core/serial_cp2130.c b/core/serial_cp2130.c > new file mode 100644 > index 0000000..e6fb659 > --- /dev/null > +++ b/core/serial_cp2130.c > @@ -0,0 +1,283 @@ > +/* > + * This is code from and inspired by > https://www.silabs.com/Support%20Documents/TechnicalDocs/AN792.pdf > + */ > + > +#include <string.h> // memset > +#include <stdlib.h> // malloc, free > +#include <stdbool.h> // bool > +/* > +#include <errno.h> // errno > +#include <sys/time.h> // gettimeofday > +#include <time.h> // nanosleep > +#include <stdio.h> > +*/ > + > +#include <libusb.h> > +#include <ftdi.h> > + > +#include <libdivecomputer/custom_serial.h> > + > +typedef struct cp2130_serial_t { > + /** libusb's context */ > + struct libusb_context *context; > + /** libusb's usb_dev_handle */ > + struct libusb_device_handle *cp2130Handle; > + /** Should we re-attach native driver? */ > + bool kernelAttached; > + > + long timeout; > +} cp2130_serial_t; > + > +static dc_status_t cp2130_serial_close (void **userdata); > +/* > +8.1.3. Initialization and Device Discovery > +The sample application shows the calls necessary to initialize and discover > a device. > +The steps that need to be taken to get a handle to the CP2130 device are: > +1. Initialize LibUSB using libusb_init(). > +2. Get the device list using libusb_get_device_list() and find a device to > connect to. > +3. Open the device with LibUSB using libusb_open(). > +4. Detach any existing kernel connection by checking > libusb_kernel_driver_active() and using > +libusb_detach_kernel_driver() if it is connected to the kernel. > +5. Claim the interface using libusb_claim_interface(). > +Here is the program listing from the sample application with comments for > reference: > +*/ > +static dc_status_t cp2130_serial_open (void **userdata, const char* name) { > + // Allocate memory. > + cp2130_serial_t *device = (cp2130_serial_t*) malloc (sizeof > (cp2130_serial_t)); > + libusb_device **deviceList = NULL; > + struct libusb_device_descriptor deviceDescriptor; > + libusb_device *usb_device = NULL; > + dc_status_t rc = DC_STATUS_SUCCESS; > + > + if (device == NULL) > + return DC_STATUS_NOMEMORY; > + > + memset(device, 0, sizeof (cp2130_serial_t)); > + > + // Default to blocking io > + device->timeout = -1; > + > + // Initialize libusb > + if (libusb_init(&device->context) != 0) > + goto exit; > + > + // Search the connected devices to find and open a handle to the CP2130 > + size_t deviceCount = libusb_get_device_list(device->context, > &deviceList); > + if (deviceCount <= 0) > + goto exit; > + > + for (int i = 0; i < deviceCount; i++) { > + if (libusb_get_device_descriptor(deviceList[i], > &deviceDescriptor) == 0) { > + if ((deviceDescriptor.idVendor == 0x10C4) && > (deviceDescriptor.idProduct == 0x87A0)) { > + usb_device = deviceList[i]; > + break; > + } > + } > + } > + if (usb_device == NULL) { > + rc = DC_STATUS_NODEVICE; > + goto exit; > + } > + > + // If a device is found, then open it > + if (libusb_open(usb_device, &device->cp2130Handle) != 0) { > + rc = DC_STATUS_IO; > + goto exit; > + } > + > + // See if a kernel driver is active already, if so detach it and store a > + // flag so we can reattach when we are done > + if (libusb_kernel_driver_active(device->cp2130Handle, 0) != 0) { > + libusb_detach_kernel_driver(device->cp2130Handle, 0); > + device->kernelAttached = true; > + } > + // Finally, claim the interface > + if (libusb_claim_interface(device->cp2130Handle, 0) != 0) { > + rc = DC_STATUS_IO; > + goto exit; > + } > + > + *userdata = device; > + > + if (deviceList) > + libusb_free_device_list(deviceList, 1); > + > + return rc; > + > +exit: > + if (deviceList) > + libusb_free_device_list(deviceList, 1); > + > + (void)cp2130_serial_close((void**)&device); > + > + return rc; > +} > + > +/* > +8.1.4. Uninitialization > +The sample code also shows the calls necessary to uninitialize a device. > +The steps need to be taken to disconnect from the CP2130 device are: > +1. Release the interface using libusb_release_interface(). > +2. Reattach from the kernel using libusb_attach_kernel_driver() (only if the > device was connected to the > +kernel previously). > +3. Close the LibUSB handle using libusb_close(). > +4. Free the device list we obtained originaly using > libusb_free_device_list(). > +5. Uninitialize LibUSB using libusb_exit(). > +Here is the program listing from the sample application for reference: > +*/ > +static dc_status_t cp2130_serial_close (void **userdata) { > + cp2130_serial_t *device = (cp2130_serial_t*) *userdata; > + > + if (device == NULL) > + return DC_STATUS_SUCCESS; > + > + if (device->cp2130Handle) > + libusb_release_interface(device->cp2130Handle, 0); > + if (device->kernelAttached) > + libusb_attach_kernel_driver(device->cp2130Handle, 0); > + if (device->cp2130Handle) > + libusb_close(device->cp2130Handle); > + if (device->context) > + libusb_exit(device->context); > + > + free(device); > + > + return DC_STATUS_SUCCESS; > +} > + > +/* > +8.1.5.1. Control Requests > +The example GPIO function will get/set the GPIO values with a control > request. Each of the commands defined in > +section "6. Configuration and Control Commands (Control Transfers)" can be > used with the LibUSB control > +request function. Each of the paramaters will map to the LibUSB function. In > this example we will refer to section > +"6.6. Get_GPIO_Values (Command ID 0x20)" . > +In this command there is a bmRequestType, bRequest and wLength. In this case > the other paramaters, wValue > +and wIndex, are set to 0. These parameters are used directly with the > libusb_control_transfer_function and it will > +return the number of bytes transferred. Here is the definition: > + > +int libusb_control_transfer(libusb_device_handle* dev_handle, uint8_t > bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned > char* data, uint16_t wLength, unsigned int timeout) > + > +After putting the defined values from section "6.6.2. Setup Stage (OUT > Transfer)" in the function, this is the resulting call to get the GPIO > + > +unsigned char control_buf_out[2]; > +libusb_control_transfer(cp2130Handle, 0xC0, 0x20, 0x0000, 0x0000, > control_buf_out, sizeof(control_buf_out), usbTimeout); > + > +*/ > + > +/* > +8.1.5.2. Bulk OUT Requests > +The example write function will send data to the SPI MOSI line. To perform > writes, use the description in section > +"5.2. Write (Command ID 0x01)" to transmit data with the LibUSB bulk > transfer function. Here is the definition: > +int libusb_bulk_transfer(struct libusb_device_handle* dev_handle, unsigned > char endpoint, > +unsigned char* data, int length, int * transferred, unsigned int timeout) > +To perform a write to the MOSI line, pack a buffer with the specified data > and payload then send the entire packet. > +Here is an example from the sample application that will write 6 bytes to > endpoint 1: > +*/ > +static dc_status_t cp2130_serial_write(void **userdata, const void *data, > size_t size, size_t *actual) { > + cp2130_serial_t *device = (cp2130_serial_t*) *userdata; > + int libusb_status; > + int bytesWritten; > + > + if (device == NULL) > + return DC_STATUS_SUCCESS; > + > + unsigned char write_command_buf[14] = { > + 0x00, 0x00, // Reserved > + 0x01, // Write command > + 0x00, // Reserved > + // Number of bytes, little-endian > + size & 0xFF, > + (size >> 8) & 0xFF, > + (size >> 16) & 0xFF, > + (size >> 24) & 0xFF, > + }; > + > + libusb_status = libusb_bulk_transfer(device->cp2130Handle, 0x01, > write_command_buf, sizeof(write_command_buf), &bytesWritten, device->timeout); > + > + if (libusb_status != 0 || bytesWritten != sizeof(write_command_buf)) > + return DC_STATUS_IO; // Simplified for now. > + > + libusb_status = libusb_bulk_transfer(device->cp2130Handle, 0x01, > (unsigned char*) data, size, &bytesWritten, device->timeout); > + > + if (actual) > + *actual = bytesWritten; > + > + if (libusb_status == 0) > + return DC_STATUS_SUCCESS; > + else > + return DC_STATUS_IO; // Simplified for now. > +} > +/* > +The function will return 0 upon success, otherwise it will return an error > code to check for the failure reason. > +*/ > + > +/* > +8.1.5.3. Bulk IN Requests > +Note: Because there is no input to the SPI the read is commented out. The > code itself demonstrates reading 6 bytes, but will > +not succeed since there is nothing to send this data to the host. This code > is meant to serve as an example of how to > +perform a read in a developed system. > +The example read function will send a request to read data from the SPI MISO > line. To perform reads, use the > +description in section "5.1. Read (Command ID 0x00)" to request data with > the LibUSB bulk transfer function (see > +definition in "8.1.5.2. Bulk OUT Requests" , or the LibUSB documentation). > +To perform a read from the MISO line, pack a buffer with the specified read > command then send the entire packet. > +Immediately after that, perform another bulk request to get the response. > Here is an example from the sample > +application that will try to read 6 bytes from endpoint 1: > +*/ > + > +static dc_status_t cp2130_serial_read (void **userdata, void *data, size_t > size, size_t *actual) { > + cp2130_serial_t *device = (cp2130_serial_t*) *userdata; > + int libusb_status; > + int bytesWritten, bytesRead; > + > + if (device == NULL) > + return DC_STATUS_SUCCESS; > + > + // This example shows how to issue a bulk read request to the SPI MISO > line > + unsigned char read_command_buf[14] = { > + 0x00, 0x00, // Reserved > + 0x00, // Read command > + 0x00, // Reserved > + // Read number of bytes, little-endian > + size & 0xFF, > + (size >> 8) & 0xFF, > + (size >> 16) & 0xFF, > + (size >> 24) & 0xFF, > + }; > + > + libusb_status = libusb_bulk_transfer(device->cp2130Handle, 0x01, > read_command_buf, sizeof(read_command_buf), &bytesWritten, device->timeout); > + > + if (libusb_status != 0 || bytesWritten != sizeof(read_command_buf)) > + return DC_STATUS_IO; // Simplified for now. > + > + libusb_status = libusb_bulk_transfer(device->cp2130Handle, 0x01, > (unsigned char*) data, size, &bytesRead, device->timeout); > + > + if (actual) > + *actual = bytesRead; > + > + if (libusb_status == 0) > + return DC_STATUS_SUCCESS; > + else > + return DC_STATUS_IO; // Simplified for now. > +} > +/* > +The bulk transfer function will return 0 upon success, otherwise it will > return an error code to check for the failure > +reason. In this case make sure to check that the bytesWritten is the same as > the command buffer size as well as a > +successful transfer. > +*/ > + > +dc_custom_serial_t cp2130_serial_ops = { > + .userdata = NULL, > + .open = cp2130_serial_open, > + .close = cp2130_serial_close, > + .read = cp2130_serial_read, > + .write = cp2130_serial_write, > +// NULL means NOP > + .purge = NULL, > + .get_available = NULL, > + .set_timeout = NULL, > + .configure = NULL, > + .set_dtr = NULL, > + .set_rts = NULL, > + .set_halfduplex = NULL, > + .set_break = NULL > +}; > diff --git a/packaging/android/build.sh b/packaging/android/build.sh > index f96a229..cf06fd9 100644 > --- a/packaging/android/build.sh > +++ b/packaging/android/build.sh > @@ -27,7 +27,7 @@ else > fi > > # Configure where we can find things here > -export > ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT-$SUBSURFACE_SOURCE/../android-ndk-r12} > +export > ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT-$SUBSURFACE_SOURCE/../android-ndk-r12b} > > if [ ! -z "$QT5_ANDROID" ] ; then > echo "Using Qt5 in $QT5_ANDROID" > diff --git a/scripts/build.sh b/scripts/build.sh > index 873bba7..7baaa11 100755 > --- a/scripts/build.sh > +++ b/scripts/build.sh > @@ -59,6 +59,8 @@ else > BUILDGRANTLEE=1 > BUILDMARBLE=1 > fi > +BUILDGRANTLEE=0 > +BUILDMARBLE=0 > > if [[ ! -d "subsurface" ]] ; then > echo "please start this script from the directory containing the > Subsurface source directory" > @@ -167,6 +169,7 @@ if [ $PLATFORM = Darwin ] ; then > exit 1 > fi > fi > +export CMAKE_PREFIX_PATH=~/Downloads/Qt/5.7/gcc_64/lib/cmake > if [ "$BUILDMARBLE" = "1" ] ; then > cmake -DCMAKE_BUILD_TYPE=Release -DQTONLY=TRUE -DQT5BUILD=ON \ > -DCMAKE_INSTALL_PREFIX=$INSTALL_ROOT \ > @@ -241,7 +244,7 @@ for (( i=0 ; i < ${#BUILDS[@]} ; i++ )) ; do > > mkdir -p $SRC/subsurface/$BUILDDIR > cd $SRC/subsurface/$BUILDDIR > - export CMAKE_PREFIX_PATH="$INSTALL_ROOT/lib/cmake;${CMAKE_PREFIX_PATH}" > +# export CMAKE_PREFIX_PATH="$INSTALL_ROOT/lib/cmake;${CMAKE_PREFIX_PATH}" > cmake -DCMAKE_BUILD_TYPE=Debug .. \ > -DSUBSURFACE_TARGET_EXECUTABLE=$SUBSURFACE_EXECUTABLE \ > -DLIBGIT2_INCLUDE_DIR=$INSTALL_ROOT/include \ > @@ -250,8 +253,12 @@ for (( i=0 ; i < ${#BUILDS[@]} ; i++ )) ; do > -DLIBDIVECOMPUTER_LIBRARIES=$INSTALL_ROOT/lib/libdivecomputer.a > \ > -DMARBLE_INCLUDE_DIR=$INSTALL_ROOT/include \ > > -DMARBLE_LIBRARIES=$INSTALL_ROOT/lib/libssrfmarblewidget.$SH_LIB_EXT \ > - -DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH \ > - -DNO_PRINTING=OFF > + -DNO_MARBLE=ON \ > + -DFBSUPPORT=OFF \ > + -DNO_USERMANUAL=ON \ > + -DNO_PRINTING=ON > + > +# -DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH \ > > if [ $PLATFORM = Darwin ] ; then > rm -rf Subsurface.app > -- > 2.7.4 -- Anton Lundin +46702-161604 _______________________________________________ subsurface mailing list subsurface@subsurface-divelog.org http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface