libftdi Archives

Subject: Re: control multiple devices with same VID/PID independently

From: Ryan Tennill <rtennill@xxxxxxxxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Date: Wed, 12 Sep 2012 18:54:41 -0500
On Wed, 2012-09-12 at 16:15 -0500, Ryan Tennill wrote:
> I need to open and monitor LOTS (> 50) of FTDI devices on a single
> computer as serial ports with CBUS GPIO. We're using one of the FT232R's
> CBUS pins as power enable and UART activity for now.
> 
> Is there a standard way for opening and controlling multiple devices
> simultaneously and independently? Even when I only create one child
> process and open one device, the call to ftdi_set_bitmode() is sent to
> ALL DEVICES even ones not explicitly opened!
> 
> I am using libftdi 0.20 and libusb0.1 which may not be thread-safe...
> http://developer.intra2net.com/mailarchive/html/libftdi/2012/msg00118.html
> 
> If libftdi-1.0 / libusb-1.0 thread-safe then I should probably consider
> switching over but I still don't understand why my set_bitmode() goes to
> all attached FT232's...
> 
> Pseudocode:
>  - ftdi_new()
>  - ftdi_init()
>  - ftdi_usb_find_all()
>  - for all found devices 
>     - ftdi_usb_open_desc_index(ftdi,DEVICE_VID,DEVICE_PID,NULL,NULL,i)
>     - read chipID and get serial from EEPROM
>     - ftdi_usb_close(ftdi) after reads
>     - fork() and child execl()'s another program to manage UART 
>       and CBUS after parent exits
>     - parent sets process group ID of child to new group shared
>       by all children (** this might be a problem too ? **)
>  - once all children processes created and running, parent 
>    cleans up eeprom, ftdi_dev_list, ftdi_deinit, and exits
> 
> 
> The child process opens devices by serial using the following call:
>   ftdi_usb_open_desc(ftdi, DEVICE_VID, DEVICE_PID,NULL,ftdi_serial)
> 
> 
> --
> libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
> To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   
> 

Here's a modified version of the bitbang example that eliminates the
possible issues from fork()'ing. If anyone has multiple devices of the
same type can they give this a shot?

//CODE
/***************************************************************************
                             main.c  -  description
                           -------------------
    begin                : Mon Apr  7 12:05:22 CEST 2003
    copyright            : (C) 2003,2008 by Intra2net AG
    email                : opensource@xxxxxxxxxxxxx

***************************************************************************/

/***************************************************************************
 *
*
 *   This program is free software; you can redistribute it and/or
modify  *
 *   it under the terms of the GNU General Public License version 2 as
*
 *   published by the Free Software Foundation.
*
 *
*

***************************************************************************/

//Modified by Ryan Tennill @ Distant Focus Corp 2012
//Goal: test CBUS I/O control using libFTDI with FT232R and Ubuntu 10.04
//Note: Requires CBUS configured as I/O in EEPROM
//Note: Requires RXD, TXD inverted in EEPROM
//Note: Driving CBUS HIGH=ON, LOW=OFF

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ftdi.h"

//my constants
#define MCCM_ON         0xFF
#define MCCM_OFF        0xF0

//ftdi defaults
#define DEFAULT_PID     0x6001
#define DEFAULT_VID     0x0403

//easily change initial device VID and PID
#define DEVICE_VID      DEFAULT_VID
#define DEVICE_PID      DEFAULT_PID
//#define DEVICE_PID      0x6015 //FT230X

//debug defines
#define PRINT_RAW_EEPROM    0
#define PRINT_EEPROM_STRUCT 1


void cleanup(struct ftdi_context *ftdi){
    printf("FTDI close: %d\n", ftdi_usb_close(ftdi));
    if(ftdi != NULL) ftdi_deinit(ftdi);
    printf("\n");
}

int main(int argc, char *argv[]) {
        
    struct ftdi_context *ftdi;
    unsigned char mychar;
    int f = 0;
    
    if ((ftdi = ftdi_new()) == 0)    {
        printf("ftdi_new failed\n");
        return EXIT_FAILURE;
    }
       
    if (ftdi_usb_open(ftdi, DEVICE_VID, DEVICE_PID)) {
        printf("Unable to find FTDI devices under given vendor/product
id: 0x%X/0x%X\n", \
                DEVICE_VID, DEVICE_PID);
        printf("Retrying with default FTDI id.\n");

        if (ftdi_usb_open(ftdi, DEFAULT_VID, DEFAULT_PID)) {
                printf("Error: %s\n", ftdi->error_str);
                exit (-1);
        }else{
            printf("device opened with default VID, PID\n");
        }

    }else{
        printf("sucessfully opened device with VID, PID: 0x%04X | 0x%04X
\n",DEVICE_VID,DEVICE_PID);
    }
    
    mychar = MCCM_OFF;
    printf("driving LOW\n");
    if ((f=ftdi_set_bitmode(ftdi, mychar, BITMODE_CBUS)<0)) {
        printf("write failed for 0x%x, error %d (%s)\n",mychar,f,
ftdi_get_error_string(ftdi));
    }
    printf("set_bitmode returned: %d\n",f);
    sleep(3);
    
    
    mychar = MCCM_ON;
    printf("driving HIGH\n");
    if ((f=ftdi_set_bitmode(ftdi, mychar, BITMODE_CBUS)<0)) {
        printf("write failed for 0x%x, error %d (%s)\n",mychar,f,
ftdi_get_error_string(ftdi));
    }
    printf("set_bitmode returned: %d\n",f);
    sleep(3);
    
    mychar = MCCM_OFF;
    printf("driving LOW\n");
    if ((f=ftdi_set_bitmode(ftdi, mychar, BITMODE_CBUS)<0)) {
        printf("write failed for 0x%x, error %d (%s)\n",mychar,f,
ftdi_get_error_string(ftdi));
    }
    printf("set_bitmode returned: %d\n",f);
    
    printf("test completed\n");
    
    cleanup(ftdi);
    return 0;
}






--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   

Current Thread