2

Iḿ trying the following: - we have a AXIS-controler which is connected to the Linux (18.04) via an CP2102-chip to an USB-port. We want to read the values of the GPIO 0-3-bits via a C-program on the linux-machine.

In my C-program I do see the USB-port and when I read the configuration it shows all the right information:

bLength: 12
bDescriptorType: 01
bcdUSB: 0200
bDeviceClass: 00
bDeviceSubClass: 00
bDeviceProtocol: 00
bMaxPacketSize: 40
idVendor: 10C4
idProduct: EA60
bcdDevice: 0100
biManufacturer: 01
iProduct: 02
iSerialNumber: 0003
iNumConfigurations: 01
Config descriptor CP210x
bLength: 09
bDescriptorType: 02
wTotalLength: 0020
bNumInterfaces: 01
bConfigurationValue: 01
iConfiguration: 00
bmAttributes: 0080
MaxPower: 32

For me this means I'ḿ connected to the correct serial device (/dev/ttyUSB0 in my case).

Now it is very unclear to my which calls I can make to read these GPIO-bits. So far I can´t find any linux-API-calls which I can use in my program.

The source-code I wrote (not perfect, but it is just for test. When it works I will clean it up)


#include <stdio.h>
#include <stdlib.h>
#include <usb.h>

int main()
{
    int nr_of_busses;
    int nr_of_devices;
    int j, r;

    struct usb_bus               *usb_busses;
    struct usb_bus               *ptr_usb_busses;
    struct usb_device            *ptr_usb_devices;
    struct usb_device_descriptor  desc;
    uint8_t                       path[8];

    usb_init();

    perror( "Init LibUSB" );

    nr_of_busses = usb_find_busses();
    fprintf( stderr, "Nr of busses found: %i\n", nr_of_busses );

    nr_of_devices = usb_find_devices();

    fprintf( stderr, "Nr of devices found: %i\n", nr_of_devices );

    usb_busses = usb_get_busses();

    if ( usb_busses == NULL ) {
        fprintf(stderr, "USB_busses = NULL\n");
        perror( "Get busses" );
    }
    else {

        ptr_usb_busses = usb_busses;

        while ( ptr_usb_busses != NULL ) {
            fprintf( stderr, "USB Buss : %s\n", ptr_usb_busses->dirname );
            fflush( stderr );

            ptr_usb_devices = ptr_usb_busses->devices;

            while (ptr_usb_devices != NULL) {
                fprintf( stderr, "FileName : %s\n", ptr_usb_devices->filename );
                fflush( stderr );

sleep(3);

// Check if this is the cp210x-device I´m looking for. If so print the information, just to be sure and to compare with the documentation

                if (ptr_usb_devices->descriptor.idProduct == 0xEA60 ) {
                    fprintf(stderr, "bLength: %02X\nbDescriptorType: %02X\nbcdUSB: %04X\nbDeviceClass: %02X\nbDeviceSubClass: %02X\n",
                                    ptr_usb_devices->descriptor.bLength,
                                    ptr_usb_devices->descriptor.bDescriptorType,
                                    ptr_usb_devices->descriptor.bcdUSB,
                                    ptr_usb_devices->descriptor.bDeviceClass,
                                    ptr_usb_devices->descriptor.bDeviceSubClass );

                    fprintf(stderr, "bDeviceProtocol: %02X\nbMaxPacketSize: %02X\nidVendor: %04X\nidProduct: %04X\nbcdDevice: %04X\n",
                                    ptr_usb_devices->descriptor.bDeviceProtocol,
                                    ptr_usb_devices->descriptor.bMaxPacketSize0,
                                    ptr_usb_devices->descriptor.idVendor,
                                    ptr_usb_devices->descriptor.idProduct,
                                    ptr_usb_devices->descriptor.bcdDevice );
                    fprintf(stderr, "biManufacturer: %02X\niProduct: %02X\niSerialNumber: %04X\niNumConfigurations: %02X\n",
                                    ptr_usb_devices->descriptor.iManufacturer,
                                    ptr_usb_devices->descriptor.iProduct,
                                    ptr_usb_devices->descriptor.iSerialNumber,
                                  ptr_usb_devices->descriptor.bNumConfigurations );

                    fprintf ( stderr, "Config descriptor CP210x\n");
                    fprintf( stderr, "bLength: %02X\nbDescriptorType: %02X\nwTotalLength: %04X\nbNumInterfaces: %02X\n",
                                    ptr_usb_devices->config->bLength,
                                    ptr_usb_devices->config->bDescriptorType,
                                    ptr_usb_devices->config->wTotalLength,
                                    ptr_usb_devices->config->bNumInterfaces   );
                    fprintf( stderr, "bConfigurationValue: %02X\niConfiguration: %02X\nbmAttributes: %04X\nMaxPower: %02X\n",
                                    ptr_usb_devices->config->bConfigurationValue,
                                    ptr_usb_devices->config->iConfiguration,
                                    ptr_usb_devices->config->bmAttributes,
                                    ptr_usb_devices->config->MaxPower   );
                    fflush( stderr );

                    usb_dev_handle *handle = usb_open( ptr_usb_devices );

// dev_dbg( ptr_usb_devices, "Test");
perror( "usb_open : ");

                    int stat = usb_set_configuration( handle, ptr_usb_devices->config->bConfigurationValue );

perror( "usb_set_configuration : ");

                    int interfaceNum = ptr_usb_devices->config->interface->altsetting->bInterfaceNumber;
                    stat = usb_claim_interface( handle, interfaceNum );

                    int altNum = ptr_usb_devices->config->interface->altsetting->bAlternateSetting;
                    stat = usb_set_altinterface( handle, altNum );

perror( "usb_set_altinterface : ");


// Now I need forever to read the GPIO-bits. How do I do that?

                    while (1) {


                    }
                }
                fprintf(stderr, "\n");
                fflush( stderr );
                ptr_usb_devices = ptr_usb_devices->next;
            }
            ptr_usb_busses = ptr_usb_busses->next;
        }

        fprintf( stderr, "All bus-names printed" );
        fflush( stderr );
    }

    exit(0);
}

After compilation I run the above program via sudo ./a.out.
Now I've got the following issues:

  • I get the following error-messages:
    • usb_open : : Inappropriate ioctl for device
    • usb_set_configuration : : Device or resource busy
    • usb_set_altinterface : : Device or resource busy

Also I really can't find the C-calls I can use to read the GPIO-bits in this program.
Is there a library to link in which the correct calls are described?
There is probably a very simple solution for this, but I can't find it, so probably I'm looking at the wrong places.

0

It is not that you get it wrong, you just hit the time wall. Advice, There is much aged documentation in Internet you better start checking last modification date before reading it.

There are two ways to make a USB driver. Or we may say two types of drivers

  1. Kernel space driver, driver in kernel tree or as module

    • Long term solution but not an easy path
  2. User space driver, driver using libusb (which by itself uses a generic kernel driver)

    • Kind of workaround but quicker & relatively easier
    • People tend to use such approach for multiple reasons: reverse engineering, prototyping, short release cycle for end user project (like: sane for scanners), as workaround for missing kernel driver,...

Probably, you found some posts that trying to access USB devices without kernel driver.

However for your case, CP210x has a kernel space driver and already got GPIO feature implemented. May be it wasn't earlier so many people get to know about it. No need to go through libusb path, otherwise you have to implement many functions from scratch following CP210x datasheet.

Silicon Labs already documented it

How to control GPIOs of CP210x at runtime

07/25/2018 | 04:56 am

On Linux

The CP210x driver has been distributed as part of the Linux kernel since v2.6.12, and GPIO operations also be supported by Linux 4.10.0 kernel or later.

If you are using an older kernel version, please download the latest Linux VCP driver from link below and merge the GPIO operation related source code into your kernel. The .zip package contains VCP driver and example code show how to control GPIOs.

https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers .

After merging the VCP driver cp210x.c, compile it with make command and install it with command "insmod ". Note that the command "rmmod cp210x.ko" should be executed if VCP driver already exists before installing the driver that support GPIO control.

In the cp210x_gpio_example.c, use the following function to open a CP210x device.

fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

Use the function below to read latch, where the third parameter gpioread is a buffer address of one-byte length for storing the read latch value.

ioctl(fd, IOCTL_GPIOGET, &gpioread);

The returned read latch value is represented as follows: bits 0–7: Current latch state, where bit 0 is GPIO0, bit 1 is GPIO1, etc. Up to GPIOn where n is the total number of GPIO pins the interface supports.

Use the function below to write latch, where the third parameter gpio is write latch value.

ioctl(fd, IOCTL_GPIOSET, &gpio);

The write latch value that is supplied in the Data phase represents as follows:

bits 0–7: Mask of the latch state (in bits 8-15) to write, where bit 0 is GPIO0, bit 1 is GPIO1, etc. Up to GPIOn where n is the total number of GPIO pins the interface supports.

bits 8–15: Latch state to write, where bit 8 is GPIO0, bit 9 is GPIO1, etc. Up to GPIOn where n is the total number of GPIO pins the interface supports.

Get more information from AN571.

Compile the application with “gcc cp210x_gpio_example.c”, a executable file “a.out” is generated. Execute it with “./a.out”.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.