FTDI LibMPSSE SPI - linux

I recently purchased the FTDI C232HM-DDHSL-0 USB cable for use with SPI and I2C devices; my goal is to read the memory from an SPI memory chip that I removed from a router. However, I am having issues getting the libMPSSE library & 2xx drivers to send signals to a connected device.I hooked the leads of the C232 up to a Saleae logic analyzer and saw that no signals were being output!
Useful links for this question:
FTDI C232HM-DDHSL-0 (purchase):
https://www.ftdichip.com/Products/Cables/USBMPSSE.htm
C232HM-DDHSL-0 data sheet:
https://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_C232HM_MPSSE_CABLE.PDF
Memory Chip data sheet: https://www.macronix.com/Lists/Datasheet/Attachments/7370/MX25L6406E,%203V,%2064Mb,%20v1.9.pdf
2xx drivers: https://www.ftdichip.com/Drivers/D2XX.htm
MPSSE SPI library:
https://www.ftdichip.com/Support/SoftwareExamples/MPSSE/LibMPSSE-SPI.htm
I am using a Debian x86_64 machine. The MPSSE SPI download only had the i386 version of the library, so I downloaded the MPSSE SPI source (https://www.ftdichip.com/Support/SoftwareExamples/MPSSE/LibMPSSE-SPI.htm) and built the x86_64 bit version. There were no build errors or warnings.
I copied libftd2xx.so and libMPSSE.so to /usr/local/lib.
I plugged the cable in, then removed the following kernel modules:
ftdi_sio <-- Readme says to take take out
usbserial <-- Readme says to take out
usb_wann <-- Needed to remove to take out usbserial
qcserial <-- Needed to remove to take out usbserial
At this point I was hoping that my set up was done correctly.
I connected 6x cables to the 8 pin memory chip:
VCC <--> red lead
Ground <--> black lead
Chip select <--> brown lead
Data in <--> green
serial clock <--> orange
Data out <--> yellow
I did not connect hold and write protect pins on the memory chip. Recall my goal is to read the memory out of the chip, and the waveform for the read did not show those pins were necessary.
I am using this program:
/* Standard C libraries */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "ftd2xx.h"
#include "libMPSSE_spi.h"
FT_HANDLE ftHandle;
uint8 tx_buffer[4096] = {0};
uint8 rx_buffer[4096] = {0};
int main()
{
uint8 i = 0;
int sizeToTransfer = 0;
int sizeTransfered = 0;
FT_STATUS status = FT_OK;
FT_DEVICE_LIST_INFO_NODE devList = {0};
ChannelConfig channelConf = {0};
channelConf.ClockRate = 30000000; // 30Mhz
channelConf.LatencyTimer = 75;
channelConf.configOptions = SPI_CONFIG_OPTION_MODE0 | SPI_CONFIG_OPTION_CS_DBUS3 | SPI_CONFIG_OPTION_CS_ACTIVELOW;
channelConf.Pin = 0x00000000;/*FinalVal-FinalDir-InitVal-InitDir (for dir 0=in, 1=out)*/
//
// Open the channel and dump some information
//
status = SPI_GetChannelInfo(0,&devList);
if (status != FT_OK)
{
printf("SPI_GetChannelInfo failed, status = %d\n", status);
return -1;
}
printf("Flags=0x%x\n",devList.Flags);
printf("Type=0x%x\n",devList.Type);
printf("ID=0x%x\n",devList.ID);
printf("LocId=0x%x\n",devList.LocId);
printf("SerialNumber=%s\n",devList.SerialNumber); // TODO: Why blank?
printf("Description=%s\n",devList.Description);
printf("ftHandle=0x%p\n",devList.ftHandle);/*is 0 unless open*/
//
// Open channel 0
//
status = SPI_OpenChannel(0,&ftHandle);
if (status != FT_OK)
{
printf("SPI_OpenChannel failed, status = %d\n", status);
return -1;
}
//
// Initialize the channel: See configuration structure at top of main()
//
status = SPI_InitChannel(ftHandle,&channelConf);
if (status != FT_OK)
{
printf("SPI_InitChannel failed, status = %d\n", status);
return -1;
}
//
// Send the read command (0x03), and read what we get in our receive buffer
//
sizeToTransfer=8;
sizeTransfered=0;
tx_buffer[0] = 0x03;
status = SPI_ReadWrite(ftHandle, rx_buffer, tx_buffer, sizeToTransfer, &sizeTransfered,
SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE|SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
if (status != FT_OK)
{
printf("SPI_ReadWrite failed, status = %d\n", status);
return -1;
}
//
// Dump the receive buffer to see if we got anything.
//
printf("Size transfered = %d\n", sizeTransfered);
i = 0;
while (i < sizeTransfered)
{
printf("%02x",rx_buffer[i]);
i++;
}
printf("\n");
//
// Cleanup
//
status = SPI_CloseChannel(ftHandle);
if (status != FT_OK)
{
printf("SPI_CloseChannel failed, ret = %d\n", status);
}
return 0;
}
To make and run the program:
To compile: gcc read_memory.c -lMPSSE -ldl
To run: sudo ./a.out
My output is:
// The driver can at least detect the cable.
Flags=0x2
Type=0x8
ID=0x4036001
LocId=0x204
SerialNumber=
Description=USB <-> Serial
ftHandle=0x(nil)
Size transfered = 8
// Junk in the receive buffer
ff037fffffffffff
Whether I keep the memory chip connected or disconnected I get the same junk in the receive buffer. I see no LEDs light up on the cable or anything to indicate it is "working." I have tried SPI_Write() and SPI_Read() and get similar behavior. I tested on an Ubuntu VM (running on Windows host) and saw the exact same behavior.
I am really excited to get this to work so if anyone can help me with what I am doing wrong it would be greatly appreciated! Thanks!

Set device first to MPSSE mode, and it should work. See quite minimum (Python) example below based on FTD2XX library only (tested in Windows). LibMPSSE is not required to run simple SPI. Data can be read by s = dev.read(nbytes), where nbytes is byte count. Find more information in nice tutorial: Driving an SPI device using MPSSE
import ftd2xx
OPS = 0x03 # Bit mask for SPI clock and data out
OE = 0x08 # CS
dev = ftd2xx.open(0) # open first available device
if dev:
dev.setTimeouts(1000, 1000)
dev.setBitMode(OPS, 2) # bit mask, MPSSE mode
dev.write(bytes((0x86, 59, 0))) # set SCK to 100kHz
dev.write(bytes((0x80, 0, OE + OPS))) # CS low
data = 0x55,
n = len(data) - 1
dev.write(bytes(((0x11, n % 256, n // 256) + data))) # write SPI data
dev.write(bytes((0x80, OE, OE + OPS))) # CS high
dev.close()

Related

Issues while reading Writting USB data

I am new to Linux operating system, i am trying to interface GSM module with USB,i interfaced USB with GSM module successfully, but i have problem while reading the data from GSM module, i can able to write data to GSM module but while reading its too difficult for me, some time i can able to read data but some time i can't able to read data, here i copy and pasted my code, please go through the code and please let me where i am failing to read data,
i need to write data normally to USB port and data should be read on interrupt based
USB configuration
int init_ttyusb0(int speed,int parity)
{
fd=open("/dev/ttyUSB1",O_RDWR|O_NDELAY|O_NOCTTY|O_APPEND,S_IRWXU|S_IRWXG|S_IRWXO);|O_NOCTTY|O_SYNC|O_NDELAY);
perror("open");
if(fd==-1)
{
perror("open");
printf("open usb driver failed\n");
//close(fd);
return 1;
}
saio.sa_handler= signal_handler_IO;
saio.sa_flags=0;
saio.sa_restorer=NULL;
sigaction(SIGIO,&saio,NULL);
fcntl(fd,F_SETFL,FNDELAY);
fcntl(fd,F_SETOWN,getpid());
tcgetattr(fd,&tty);
perror("tcgetattr");
cfsetospeed(&tty,speed);
perror("cfsetospeed");
cfsetispeed(&tty,speed);
perror("cfsetispeed");
tty.c_cflag=(tty.c_cflag&~CSIZE)|CS8; // 8bit character
tty.c_iflag&=~IGNBRK;
// tty.c_lflag=0; // No signaling break process
// tty.c_oflag=0; //No remaping no delay
tty.c_cc[VMIN]=0; // read dosen't block
tty.c_cc[VTIME]=10; //0.5 seconds
tty.c_iflag&=~(IXON|IXOFF|IXANY);
tty.c_cflag|=CLOCAL; // igniore modem controls
tty.c_cflag|=CREAD;
tty.c_cflag&=~(PARENB|PARODD);
tty.c_cflag&=~CSTOPB;
tty.c_cflag&=~CRTSCTS;
tty.c_cflag&=~ICANON; // Disabling cananicle from disbling newline
tty.c_cflag&=~ISIG; // Disabling interrupt signaling bits
// tty.c_iflag&=~(IXON|IXOFF|IXANY); // Disabling software flow control
tty.c_lflag&=~ECHO;
tty.c_lflag&=~ECHOE;
tty.c_lflag&=~ECHONL;
tty.c_lflag&=~(IXON|IXOFF|IXANY);
tty.c_oflag&=~OPOST;
tcsetattr(fd,TCSANOW,&tty);
perror("tcsetattr");
printf("UART configured.....................\n");
}
Interrupt handler
-----------------------
void signal_handler_IO(int status)
{
static int gsm_count
read(fd,&zfc_buffer[gsm_count],sizeof(zfc_buffer));
printf("%s\n",zfc_buffer);
memset(zfc_buffer,0,sizeof(zfc_buffer));
fcntl(fd,F_SETFL,!(O_ASYNC));
}
int main(void)
{
int init_ttyusb0(B9600,0)
while(1)
{
printf("\n eneter option > ");
scanf("%d",&operation);
int m=26;
switch(operation)
{
case 0:
memset(buf_rcv,0,sizeof(buf_rcv));
buf[0]='A';
buf[1]='T';
buf[2]='\r';
buf[3]='\0';
write(fd,"AT\r",3);
usleep((3+25)*100);
fcntl(fd,F_SETFL,O_ASYNC); // Enabling interrupt after write
usleep((3+25)*100);
perror("write");
break;
case 1:
write(fd,"AT+CFUN=1\r",10);
usleep(175000);
fcntl(fd,F_SETFL,O_ASYNC);// Enabling interrupt after write
break;
case 2:
memset(buf,0,sizeof(buf));
strcpy(buf,"AT+CCID\r");
write(fd,"AT+CPIN?\r",9);
usleep(150000);
fcntl(fd,F_SETFL,O_ASYNC);// Enabling interrupt after write
break;
}

No such device or address error when reading from TCA6408a I/O Expander using I2C

I have an application that I have cross-compiled for the USRP N310 that uses the TCA9548 I²C switch to read and write data to and from the TCA6408 I/O Expander on the daughterboard using the built-in Linux I2C driver. To do this, I've been following the tutorial "Implementing I2C drivers in UserSpace" attached here i2c tutorial. I've been able to test out this functionality successfully using the ZC706 embedded platform,however, I'm having issues reading data on the USRP platform. My code is the following
#include "i2c_dev.hpp"
int main()
{
int i2cfd;
__s32 num;
//Opening i2c adapter 6
printf("Opening bus adapter\n");
i2cfd = open("/dev/i2c-6", O_RDWR);
if ( i2cfd <0 )
{
printf("Failed to open /dev/i2c-6: %s\n",strerror( errno ));
return (1);
}
//Instatiating three objects of IO_Expander class
IO_Expander dba;
//Reading data from the IO Expander
printf("Setting slave address of device\n");
if (ioctl(i2cfd, I2C_SLAVE, 0x20) < 0) {
printf("Error setting slave address:%s\n",strerror(errno));
return(1);
}
printf("Reading data from the IO Expander for DB-A Object\n");
num =dba.read_data(i2cfd, 0x00);
if (num<0){
printf("Error reading data: %s\n",strerror(errno));
}
else {
printf("The input value is %d: \n", num);
}
printf("Leaving DB-A Object \n\n\n");
//Closing the adapter
close(i2cfd);
}
The printout I receive when running this application is a string error "No such device or address" when trying to read data from the I/O Expander.The slave address of the device is the 7 bit address of 010 0000 or hex 20 and the address of the input register is 0x00 according to the data sheet. At the moment, I'm unclear as to what's going wrong.I'm a bit of a newbie so I'm unsure of what to try next.
TCA9548 data sheet
TCA6408 data sheet

Why does the PL330 always trigger a RX Timeout when reading?

we are using a CycloneV FPGA system with an integrated ARM Cortex-A9 dual core processor system. This processor system is running angstrom linux with a 4.1 kernel and has a pl330 DMA core. We are trying to write a kernel module to use this DMAC to push data into the FPGA fabric and read from it.
Writing to the FPGA works (albeit pretty slow), but everytime we try to read I can see the read transfer taking place, but the linux dmaengine reports a timeout and on kernel-level, the transfer is never finished.
Does somebody know why this might happen? I can comment out the timeout logic and get data out of it, so I'm guessing it might have to do with cache-coherency or something similar.
This is the read function in our kernel module:
static int dma_start_rx(struct platform_device *pdev, unsigned datalen, unsigned char *databuf, u32 burst_size, bool isDecrypt) {
struct mRiddler_dev *pdata = platform_get_drvdata(pdev);
struct dma_chan *dmaChan;
struct dma_slave_config dmaConf;
struct dma_async_tx_descriptor *dmaDesc = NULL;
dmaChan = pdata->dma_rx_chan;
memset(&dmaConf, 0, sizeof(dmaConf)); // Clear memory for DMA config
// Build DMA configuration
dmaConf.direction = DMA_DEV_TO_MEM;
if (isDecrypt)
dmaConf.src_addr = pdata->dma_datareg_phy + RID_DMA_DATA_READ_DECRYPT;
else
dmaConf.src_addr = pdata->dma_datareg_phy + RID_DMA_DATA_READ_ENCRYPT;
#ifdef DEBUG
pr_info("Accessing device address: %u, based on dma_datareg_phy: %u\n", dmaConf.src_addr, pdata->dma_datareg_phy);
#endif
dmaConf.src_addr_width = 8;
dmaConf.src_maxburst = burst_size;
pdata->dma_rx_addr = dma_map_single(&pdev->dev, databuf, datalen, DMA_FROM_DEVICE);
// Error handling
if (dma_mapping_error(&pdev->dev, pdata->dma_rx_addr)) {
pr_err("dma_map_single for RX failed!\n");
return -EINVAL;
}
// Setup slave config
dmaengine_slave_config(dmaChan, &dmaConf);
// Get DMA descriptor
dmaDesc = dmaengine_prep_slave_single(dmaChan, pdata->dma_rx_addr, datalen, dmaConf.direction, DMA_PREP_INTERRUPT);
// Error handling
if (!dmaDesc) {
dma_shutdown(pdata);
return -ENOMEM;
}
// Set callbacks
dmaDesc->callback = dma_rx_done;
dmaDesc->callback_param = pdata;
// Get cookie and submit transfer to queue
pdata->dma_rx_cookie = dmaengine_submit(dmaDesc);
// Error handling
if (dma_submit_error(pdata->dma_rx_cookie))
pr_err("RX cookie error on dmaengine_submit\n");
#ifdef DEBUG
pr_info("Issueing RX transfer to DMA engine...\n");
#endif
// Start DMA
dma_async_issue_pending(dmaChan);
return 0;
}
EDIT: Here's where the timeout is set up and the DMA read function is called:
if (numBytes > 0) {
#ifdef DEBUG
pr_info("Calling dma_start_rx with following values: numBytes=%d, burstSize=%d\n", numBytes, burstSize);
#endif
retVal = dma_start_rx(pdata->pdev, numBytes, pdata->dma_rx_buffer, burstSize, false);
if (retVal) {
pr_err("Error starting RX DMA!\n");
return retVal;
}
if (!wait_for_completion_timeout(&dma_read_complete, msecs_to_jiffies(timeout))) {
pr_err("Timeout while waiting for RX DMA\n");
dmaengine_terminate_all(pdata->dma_rx_chan);
return -ETIMEDOUT;
}
*offset = 0;
}
This is the dmesg output when I try to read from the device:
[ 326.486364] Issueing DMA transfer...
[ 326.489952] DMA TX transfer finished!
[ 335.607286] There are 4 words available in enc_tx FIFO!
[ 335.612497] DMA read 32 > requested bytes 16, adjusting...
[ 335.617992] Now reading 16 bytes in 2 words!
[ 335.622246] Adjusted burstSize/numWords, new values: 2 and 2
[ 335.627898] Calling dma_start_rx with following values: numBytes=16, burstSize=2
[ 335.635283] Accessing device address: 3221225480, based on dma_datareg_phy: 3221225472
[ 335.643168] Issueing RX transfer to DMA engine...
[ 336.643795] Timeout while waiting for RX DMA, cookie: 2

how to implement tcpdump -i interface arp with libpcap

I want to implement command tcpdump -i eth0 arp to observe arp packets on interface eth0 on my ubuntu. I use libpcap, but the return value of function pcap_next_ex is always 0. With tcpdump -i eth0 arp in the same time , it can observe arp packets.
/*
* compile(root): gcc test.c -lpcap
* run : ./a.out
* output : time out
* time out
* time out
* ...
*/
#include <pcap.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define ARP_REQUEST 1
#define ARP_REPLY 2
typedef struct arp_hdr_s arp_hdr_t;
struct arp_hdr_s {
u_int16_t htype;
u_int16_t ptype;
u_char hlen;
u_char plen;
u_int16_t oper;
u_char sha[6];
u_char spa[4];
u_char tha[6];
u_char tpa[4];
};
#define MAXBYTES2CAPTURE 2048
int
main(int argc, char **argv)
{
char err_buf[PCAP_ERRBUF_SIZE];
const unsigned char *packet;
int i;
int ret;
arp_hdr_t *arp_header;
bpf_u_int32 net_addr;
bpf_u_int32 mask;
pcap_t *desrc;
struct pcap_pkthdr *pkthdr;
struct bpf_program filter;
net_addr = 0;
mask = 0;
memset(err_buf, 0, PCAP_ERRBUF_SIZE);
desrc = pcap_open_live("eth0", MAXBYTES2CAPTURE, 0, 512, err_buf);
if (desrc == NULL) {
fprintf(stderr, "error: %s\n", err_buf);
exit(-1);
}
ret = pcap_lookupnet("eth0", &net_addr, &mask, err_buf);
if (ret < 0) {
fprintf(stderr, "error: %s\n", err_buf);
exit(-1);
}
ret = pcap_compile(desrc, &filter, "arp", 1, mask);
if (ret < 0) {
fprintf(stderr, "error: %s\n", pcap_geterr(desrc));
exit(-1);
}
ret = pcap_setfilter(desrc, &filter);
if (ret < 0) {
fprintf(stderr, "errnor: %s\n", pcap_geterr(desrc));
exit(-1);
}
while (1) {
ret = pcap_next_ex(desrc, &pkthdr, &packet);
if (ret == -1) {
printf("%s\n", pcap_geterr(desrc));
exit(1);
} else if (ret == -2) {
printf("no more\n");
} else if (ret == 0) { // here
printf("time out\n");
continue;
}
arp_header = (arp_hdr_t *)(packet + 14);
if (ntohs(arp_header->htype) == 1 && ntohs(arp_header->ptype == 0x0800)) {
printf("src IP: ");
for (i = 0; i < 4; i++) {
printf("%d.", arp_header->spa[i]);
}
printf("dst IP: ");
for (i = 0; i < 4; i++) {
printf("%d.", arp_header->tpa[i]);
}
printf("\n");
}
}
return 0;
}
Without getting too deep in your code, I can see a major problem:
In your use of pcap_open_live(), you do not set promiscuous mode: the third parameter should be non-zero. If the ARP request is not targeted to your interface IP, pcap will not see it without promiscuous mode. tcpdump does, unless specifically told not to do so by using the --no-promiscuous-mode, use promisc (and hence will require CAP_NET_ADMIN privilege, which you'll get by sudo, which your program will require too).
Side note:
1/ Leak: you may want to free your filter using pcap_freecode() after your pcap_setfilter().
2/ I assume you've read the official tuto here:
http://www.tcpdump.org/pcap.html
...if that's not the case you'd be well advised to do that first. I quote:
A note about promiscuous vs. non-promiscuous sniffing: The two
techniques are very different in style. In standard, non-promiscuous
sniffing, a host is sniffing only traffic that is directly related to
it. Only traffic to, from, or routed through the host will be picked
up by the sniffer. Promiscuous mode, on the other hand, sniffs all
traffic on the wire. In a non-switched environment, this could be all
network traffic. [... more stuff on promisc vs non-promisc]
EDIT:
Actually, looking deeper to you code compared to my code running for +1 year at production level (both in-house and at the customer) I can see many more things that could be wrong:
You never call pcap_create()
You never call pcap_set_promisc(), we've talked about this already
You never call pcap_activate(), this may be the core issue here
...pcap is very touchy about the sequence order of operations to first get a pcap_t handle, and then operate on it.
At the moment, the best advice I can give you - otherwise this is going to a live debugging session between you and me, are:
1/ read and play/tweak with the code from the official tutorial:
http://www.tcpdump.org/pcap.html
This is mandatory.
2/ FWIW, my - definitely working - sequence of operations is this:
pcap_lookupnet()
pcap_create()
pcap_set_promisc()
pcap_set_snaplen(), you may or may not need this
pcap_set_buffer_size(), you may or may not need this
pcap_activate() with a note: Very important: first activate, then set non-blocking from PCAP_SETNONBLOCK(3PCAP): When first activated with pcap_activate() or opened with pcap_open_live() , a capture handle is not in non-blocking mode''; a call to pcap_set-nonblock() is required in order to put it intonon-blocking'' mode.
...and then, because I do not use stinking blocking/blocking with timeout, busy looping:
pcap_setnonblock()
pcap_get_selectable_fd()
...then and only then:
- pcap_compile()
- followed by a pcap_setfilter()
- and then as I mentioned a pcap_freecode()
- and then a select() or family on the file'des' I get from pcap_get_selectable_fd(), to pcap_dispatch(), but this is another topic.
pcap is an old API starting back in the 80's, and its really very very touchy. But don't get discouraged! It's great - once you get it right.
It would probably work better if you did
if (ntohs(arp_header->htype) == 1 && ntohs(arp_header->ptype) == 0x0800) {
rather than
if (ntohs(arp_header->htype) == 1 && ntohs(arp_header->ptype == 0x0800)) {
The latter evaluates arp_header->type == 0x0800, which, when running on a little-endian machine (such as a PC), will almost always evaluate to "false", because the value will look like 0x0008, not 0x0800, in an ARP packet - ARP types are big-endian, so they'll look byte-swapped on a little-endian machine). That means it'll evaluate to 0, and byte-swapping 0 gives you zero, so that if condition will evaluate to "false", and the printing code won't be called.
You'll still get lots of timeouts if you fix that, unless there's a flood of ARP packets, but at least you'll get the occasional ARP packet printed out. (I would advise printing nothing on a timeout; pcap-based programs doing live capturing should expect that timeouts should happen, and should not report them as unusual occurrences.)

libusb basic example wanted

I'm writing user-space program that is intended to control some device via usb so I decided to use libusb (libusb-1.0) to send control messages to and receive responses from that device.
But I constantly receive the following bunch of errors from my code (even when it's executed using 'sudo'):
USB error: could not set config 0: Device or resource busy
set configuration: failed
Check that you have permissions to write to 007/012 and, if you don't, that you set up hotplug (http://linux-hotplug.sourceforge.net/) correctly.
USB error: could not claim interface 0: Device or resource busy
claim interface: failed
USB error: error submitting URB: No such file or directory
bulk writing: failed
USB error: error submitting URB: No such file or directory
bulk reading: failed
response was:
The code is:
usb_dev_handle* find_device ();
int
main (int argc, char *argv[])
{
usb_dev_handle* udev;
int status;
char request[] = "K1"; // 'ping' command used to check communication
char response[256];
udev = find_device ();
// udev is successfully found here
status = usb_set_configuration (udev, 0);
printf ("set configuration: %s\n", status ? "failed" : "passed");
status = usb_claim_interface (udev, 0);
printf ("claim interface: %s\n", status ? "failed" : "passed");
status = usb_bulk_write (udev, 3, request, sizeof (request), 500);
printf ("bulk writing: %s\n", status ? "failed" : "passed");
status = usb_bulk_read (udev, 2, response, sizeof (response), 500);
printf ("bulk reading: %s\n", status ? "failed" : "passed");
printf ("response was: %s\n", response);
usb_close (udev);
return 0;
}
What's wrong with the code? And how it could be fixed?
OS: Ubuntu 10.10
Answering this question as I had faced this issue on the same OS and was able to solve in the following manner:
Download and Compile the latest libusb source code 1.0.8.
Following are some API calls that I used in order to claim USB interface 0:
libusb_init(NULL);
libusb_open_device_with_vid_pid(NULL, vendor_id, product_id);
libusb_detach_kernel_driver(devh, 0);
libusb_claim_interface(devh, 0);
libusb_close(devh);
libusb_exit(NULL);
Description of the variables in the above example:
static struct libusb_device_handle *devh = NULL;
uint16_t vendor_id;
uint16_t product_id;
To get the vendor ID and product ID, you may run the following commands (Ex. my device info)
$ lsusb
...
Bus 001 Device 013: ID 0930:6544 Toshiba Corp. Kingston DataTraveler 2.0 Stick (2GB)
...
The bold colon delimited string contains vendor and product id respectively.
How to compile the code:
I used the following command to compile my code:
/bin/bash libtool --silent --tag=CC --mode=link g++ -Wall -Wundef -Wunused -Wshadow -D_DEBUG -I../libusb -g -O2 -o read read.cpp ../libusb/libusb-1.0.la -lusb-1.0 -lrt
Copy libtool to the compilation area from the extracted libusb-1.0.8 directory.
Hope this helps.
Don't you need to open() the device before you set its configuration and claim it?
here's a generic example of a libusb program that you can adapt as needed.
also see the API, which is great!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libusb.h>
#include <err.h>
#define MFGR_ID 0 // given manufacturer ID
#define DEV_ID 0 // given device ID
/* If device IDs are not known, use libusb_get_device_list() to see a
list of all USB devices connected to the machine. Follow this call with
libusb_free_device_list() to free the allocated device list memory.
*/
int main() {
int init = libusb_init(NULL); // NULL is the default libusb_context
if (init < 0) {
errx(1,”\n\nERROR: Cannot Initialize libusb\n\n”);
}
struct libusb_device_handle *dh = NULL; // The device handle
dh = libusb_open_device_with_vid_pid(NULL,MFGR_ID,DEV_ID);
if (!dh) {
errx(1,”\n\nERROR: Cannot connect to device %d\n\n”,DEV_ID);
}
// set fields for the setup packet as needed
uint8_t bmReqType = 0; // the request type (direction of transfer)
uint8_t  bReq = 0; // the request field for this packet
uint16_t  wVal = 0; // the value field for this packet
uint16_t  wIndex = 0; // the index field for this packet
unsigned char*  data = ‘ ‘; // the data buffer for the in/output data
uint16_t  wLen = 0; // length of this setup packet
unsigned int  to = 0; // timeout duration (if transfer fails)
// transfer the setup packet to the USB device
int config =
libusb_control_transfer(dh,bmReqType,bReq,wVal,wIndex,data,wLen,to);
if (config < 0) {
errx(1,”\n\nERROR: No data transmitted to device %d\n\n”,DEV_ID);
}
// now you can use libusb_bulk_transfer to send raw data to the device
libusb_exit(NULL);
}

Resources