Related
I have written a small test program that reads a temperature register on a LSM6DSO chip and display the temperature correctly after reading the /dev/i2c (IOCTL call) so far so good but whilst reading the chip through iio_generic_buffer() (which relies on the sysfs filesystem) correctly updates the register and returns slightly different values at each read, my program keeps on displaying the same value over and
over.
So question is: What am I missing? And why doesn't the register updates itself with the next temperature?
int main()
{
...
for (i = 0; i <= 100; i++) {
i2c_read_1_byte(0x6a, 0xf, result); // reading 1 byte of register 0xf (WHO_AM_I)
printf("Read %#02X\n", result[0]);
i2c_read_1_byte(0x6a, 0x20, result);
templ = result[0];
i2c_read_1_byte(0x6a, 0x21, result);
temph = result[0];
printf("Read temph %#02X\n", temph);
printf("Read templ %#02X\n", templ);
res = (((unsigned short)temph << 8) & 0xFF00) | templ;
printf("res: 0x%x\n", res);
}
int i2c_read_1_byte(unsigned char slave_addr, unsigned char reg, unsigned char *result)
{
unsigned char outbuf[1], inbuf[1];
struct i2c_msg msgs[2];
struct i2c_rdwr_ioctl_data msgset[1];
msgs[0].addr = slave_addr;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = outbuf;
msgs[1].addr = slave_addr;
msgs[1].flags = I2C_M_RD | I2C_M_STOP;
msgs[1].len = 1;
msgs[1].buf = inbuf;
msgset[0].msgs = msgs;
msgset[0].nmsgs = 2;
outbuf[0] = reg;
inbuf[0] = 0;
*result = 0;
if (ioctl(i2c_fd, I2C_RDWR, &msgset) < 0) {
perror("ioctl(I2C_RDWR) in i2c_read");
return -1;
}
*result = inbuf[0];
return 0;
}
Solved, was a timing problem, so started with usleep and ended polling the DTA_RDY register ...
I am writing kqueue hooks for a character device that allows a client to block waiting for an EVFILT_READ. If I set my read filters code to always return one the kevent will return instantly. However, if the filter returns one at some later point in time nothing unblocks. For the following code the printf "After" never happens and in the filter code I can trivially get "filter_Read return 1" (immediately followed by a return 0)
Device (relevant excerpt)
static int
lowmem_filter_read(struct knote *kn, long hint)
{
mtx_assert(&lowmem_mtx, MA_OWNED);
if(manual_alert){
manual_alert=0;
printf("filter_Read return 1\n");
return 1;
}
printf("filter_Read return 0\n");
return 0;
}
static void
lowmem_filter_detach(struct knote *kn)
{
mtx_assert(&lowmem_mtx, MA_OWNED);
knlist_remove(&kl, kn, 0);
}
static struct filterops lowmem_filtops_read = {
.f_isfd = 1,
.f_detach = lowmem_filter_detach,
.f_event = lowmem_filter_read,
};
static int
lowmem_kqfilter(struct cdev *dev, struct knote *kn)
{
int err = EINVAL;
/* Figure out who needs service */
lowmem_lock();
switch (kn->kn_filter) {
case EVFILT_READ:
kn->kn_fop = &lowmem_filtops_read;
knlist_add(&kl, kn, 1);
err = 0;
break;
default:
err = EOPNOTSUPP;
break;
}
lowmem_unlock();
return (err);
}
Client:
struct kevent ev;
struct timespec nullts = {0,0};
int fd=0;
int main(int argc, char **argv){
fd = open("/dev/lowmem", O_RDWR | O_NONBLOCK);
int kq=kqueue();
EV_SET(&ev,fd,EVFILT_READ, EV_ADD,0,0,NULL);
kevent(kq,&ev,1,NULL,0,&nullts);
for(;;){
printf("Starting\n");
int n=kevent(kq,NULL,0,&ev,1,NULL);
printf("After\n");
if(n>0){
printf("Something happened ev.fflags=%i\n",(int)ev.fflags);
}
}
return 0;
}
i have this problem,
i have STM32 Nucleo L152RE and a Shield SIM 900,
now if i write this easy thread all work well,
'static THD_WORKING_AREA(waRead, 128);
static THD_FUNCTION(Thread,arg) {
(void)arg;
chRegSetThreadName("th_callback");
while (TRUE){
/* This will wait for a character to be received */
uint8_t c = sdGet(&SD1); //questo prende il carattere
sdPut(&SD2, c); // questo lo spara alla terminale
}
}
'
when i sand a AT commnad i see the ok answer.
Now i create this buffer
'static uint8_t bufferMsg[128];'
and i use this thread for store the answer
' static THD_WORKING_AREA(waRead5, 128);
static THD_FUNCTION(Thread5,arg) {
chRegSetThreadName("th_Riempio_Buffer");
msg_t charbuf;
int count=0;
uint8_t c;
event_listener_t Uart1Data;
eventmask_t flags;
chEvtRegisterMask((event_source_t *)chnGetEventSource(&SD1), &Uart1Data, EVENT_MASK(1));
while (TRUE) {
chEvtWaitOneTimeout(EVENT_MASK(1), MS2ST(10));
chSysLock();
flags =chEvtGetAndClearFlags(&Uart1Data);
chSysUnlock();
if (flags & CHN_INPUT_AVAILABLE)
{
do
{
charbuf = chnGetTimeout(&SD1,TIME_IMMEDIATE);
if (charbuf != Q_TIMEOUT)
{
while((charbuf != '\n') && (count < 128)) {
sdWrite(&SD2, (uint8_t *)B3,4); // va bene
bufferMsg[count]= charbuf;
count++;
}
}
}
while (charbuf != Q_TIMEOUT);
}
}
}
'
this threads don't work and don't store the answer, can you help me?
best regards
A.
fot me i use,
Define
#define buffer_size 128
char buffer[buffer_size + 1];
int nbytes = 0;
Function
void SIM_callback(){ /* GSM900 Serial */
char x = SIM.getc();
buffer[nbytes] = x;
nbytes++; if (nbytes > buffer_size) nbytes = buffer_size;
buffer[nbytes] = '\0';
}
Main
main (){
// Clear Buffer
buffer[nbytes] = '\0';
...
while(1);
...
}
We are using Linux-2.6.28 and 2 Gb NAND Flash in our system ; After some amount of power cycle tests we are observing the following errors :
Volume operational found at volume id 3
read 21966848 bytes from volume 3 to 80400000(buf address)
UBI error: ubi_io_read: error -77 while reading 126976 bytes from PEB 1074:4096, read 126976 bytes
UBI: force data checking
UBI error: ubi_io_read: error -77 while reading 126976 bytes from PEB 1074:4096, read 126976 bytes
UBI warning: ubi_eba_read_leb: CRC error: calculated 0xa7cab743, must be 0x15716fce
read err ffffffb3
These errors are not hardware errors as if we remove the offending partition, we are able to boot the hardware fine; Maybe UBIFS is not correcting the bad UBI block.
Any UBI patches have been added in the latest kernels to address this issue ? Thanks.
The error printed is a UBI error. Lets look at the source near line 177,
ubi_err("error %d while reading %d bytes from PEB %d:%d, "
"read %zd bytes", err, len, pnum, offset, read);
So, error '-77' (normally -EBADFD) was returned from the NAND flash driver when trying to read the 'physical erase block' #1074 at offset 4096 (2nd page for 2k pages). UBI include volume management pages which are typically located at the beginning of a physical erase block (PEB for short).
Note that the latest mainline of io.c has the following comment and code,
/*
* Deliberately corrupt the buffer to improve robustness. Indeed, if we
* do not do this, the following may happen:
* 1. The buffer contains data from previous operation, e.g., read from
* another PEB previously. The data looks like expected, e.g., if we
* just do not read anything and return - the caller would not
* notice this. E.g., if we are reading a VID header, the buffer may
* contain a valid VID header from another PEB.
* 2. The driver is buggy and returns us success or -EBADMSG or
* -EUCLEAN, but it does not actually put any data to the buffer.
*
* This may confuse UBI or upper layers - they may think the buffer
* contains valid data while in fact it is just old data. This is
* especially possible because UBI (and UBIFS) relies on CRC, and
* treats data as correct even in case of ECC errors if the CRC is
* correct.
*
* Try to prevent this situation by changing the first byte of the
* buffer.
*/
*((uint8_t *)buf) ^= 0xFF;
The following code can be used to process a UBI/UbiFS dump and look for abnormalities,
/* -*- mode: c; compile-command: "gcc -Wall -g -o parse_ubi parse_ubi.c"; -*- */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <endian.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define __packed __attribute__((packed))
#include "ubi-media.h"
#define bswap16 be16toh
#define bswap32 be32toh
#define bswap64 be64toh
static int dump_vid = 0;
#define CRCPOLY_LE 0xedb88320
static unsigned int crc32(unsigned int crc, void const *_p, size_t len)
{
unsigned char const *p = _p;
int i;
while (len--) {
crc ^= *p++;
for (i = 0; i < 8; i++)
crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
}
return crc;
}
#define ALEN(a) (sizeof(a)/sizeof(a[0]))
static void print_ec(struct ubi_ec_hdr *ec)
{
if(ec->version != UBI_VERSION || ec->magic != UBI_EC_HDR_MAGIC) {
printf(" Magic: %x\n", ec->magic);
printf(" Version: %d\n", (int)ec->version);
printf(" EC: %llx\n", ec->ec);
printf(" VID offset: %x\n", ec->vid_hdr_offset);
printf(" Data offset: %x\n", ec->data_offset);
printf(" Image seq: %x\n", ec->image_seq);
exit(-1);
}
}
static void read_ec(int fd, struct ubi_ec_hdr *ec)
{
int rval = read(fd, ec,sizeof(*ec));
if(rval == sizeof(*ec)) {
unsigned int crc;
crc = crc32(UBI_CRC32_INIT, ec, UBI_EC_HDR_SIZE_CRC);
ec->magic = bswap32(ec->magic);
ec->vid_hdr_offset = bswap32(ec->vid_hdr_offset);
ec->data_offset = bswap32(ec->data_offset);
ec->image_seq = bswap32(ec->image_seq);
ec->hdr_crc = bswap32(ec->hdr_crc);
ec->ec = bswap64(ec->ec);
if(crc != ec->hdr_crc)
printf("EC CRC: %x/%x\n", crc, ec->hdr_crc);
} else
memset(ec, 0, sizeof(*ec));
}
static void print_vid(int vid_num, struct ubi_vid_hdr *vid)
{
if(vid->magic != UBI_VID_HDR_MAGIC)
printf(" Magic: %x\n", vid->magic);
if(vid->version != UBI_VERSION)
printf(" Version: %d\n", (int)vid->version);
if(!dump_vid) return;
printf("VID %d\n", vid_num);
/* This is usually the same. */
if(vid->vol_id >= UBI_INTERNAL_VOL_START)
printf("Internal vol_id: %d\n", vid->vol_id - UBI_INTERNAL_VOL_START);
if(vid->vol_type != UBI_VID_DYNAMIC)
printf(" vol_type: %s\n",
vid->vol_type == UBI_VID_DYNAMIC ? "dynamic" : "static");
if(vid->used_ebs)
printf(" used_ebs: %d\n", vid->used_ebs);
if(vid->data_pad)
printf(" data_pad: %d\n", vid->data_pad);
if((vid->copy_flag != 1 && vid->data_size) ||
(vid->copy_flag == 0 && vid->data_size))
printf(" copy_flag: %d\n", (int)vid->copy_flag);
printf(" lnum: %d\n", vid->lnum);
if(vid->compat) {
const char *compat[] = {
[UBI_COMPAT_DELETE] = "delete",
[UBI_COMPAT_RO] = "ro",
[UBI_COMPAT_PRESERVE] = "preserve",
[UBI_COMPAT_REJECT] = "reject"
};
printf(" compat: %s\n", compat[vid->compat]);
}
printf(" data_size: %d\n", vid->data_size);
/* printf(" data_crc: %x\n", vid->data_crc); */
printf(" hdr_crc: %x\n", vid->hdr_crc);
printf(" sqnum: %lld\n", vid->sqnum);
}
static int read_vid(int fd, struct ubi_vid_hdr *vid)
{
int rval = read(fd, vid,sizeof(*vid));
if(rval == sizeof(*vid)) {
unsigned int crc;
crc = crc32(UBI_CRC32_INIT, vid, UBI_EC_HDR_SIZE_CRC);
vid->magic = bswap32(vid->magic);
vid->vol_id = bswap32(vid->vol_id);
vid->lnum = bswap32(vid->lnum);
vid->data_size = bswap32(vid->data_size);
vid->used_ebs = bswap32(vid->used_ebs);
vid->data_pad = bswap32(vid->data_pad);
vid->data_crc = bswap32(vid->data_crc);
vid->hdr_crc = bswap32(vid->hdr_crc);
vid->sqnum = bswap64(vid->sqnum);
if(crc != vid->hdr_crc && vid->magic == UBI_VID_HDR_MAGIC)
printf("VID CRC: %x/%x\n", crc, vid->hdr_crc);
} else
memset(vid, 0, sizeof(*vid));
return rval;
}
static void print_vtbl(struct ubi_vtbl_record *vtbl)
{
printf(" Found vtbl [%d] %s\n", vtbl->name_len, vtbl->name);
printf(" Reserved PEBs: %d\n", vtbl->reserved_pebs);
printf(" Align: %d\n", vtbl->alignment);
printf(" Pad: %d\n", vtbl->data_pad);
if(vtbl->vol_type != UBI_VID_DYNAMIC)
printf(" vol_type: %s\n",
vtbl->vol_type == UBI_VID_DYNAMIC ? "dynamic" : "static");
printf(" Update: %d\n", vtbl->upd_marker);
printf(" Flags: %d\n", (int)vtbl->flags);
}
static void read_vtbl(int fd, struct ubi_vtbl_record *vtbl)
{
int rval = read(fd, vtbl, sizeof(*vtbl));
if(rval == sizeof(*vtbl)) {
vtbl->reserved_pebs = bswap32(vtbl->reserved_pebs);
vtbl->alignment = bswap32(vtbl->alignment);
vtbl->data_pad = bswap32(vtbl->data_pad);
vtbl->crc = bswap32(vtbl->crc);
vtbl->name_len = bswap16(vtbl->name_len);
} else
memset(vtbl, 0, sizeof(*vtbl));
}
static void print_fm_sb(struct ubi_fm_sb *fm_sb)
{
int i;
if(fm_sb->magic != UBI_FM_SB_MAGIC)
printf(" Magic: %x\n", fm_sb->magic);
if(fm_sb->version != UBI_VERSION)
printf(" Version: %d\n", (int)fm_sb->version);
printf(" data_crc: %x\n", fm_sb->data_crc);
printf(" used_blocks: %x\n", fm_sb->used_blocks);
for(i = 0; i < fm_sb->used_blocks; i++)
printf(" block_loc[%d]: %d\n", i, fm_sb->block_loc[i]);
for(i=0; i < fm_sb->used_blocks; i++)
printf(" block_ec[%d]: %d\n", i, fm_sb->block_ec[i]);
printf(" sqnum: %lld\n", fm_sb->sqnum);
}
static void read_fm_sb(int fd, struct ubi_fm_sb *fm_sb)
{
int rval = read(fd, fm_sb, sizeof(*fm_sb));
if(rval == sizeof(*fm_sb)) {
int i;
fm_sb->magic = bswap32(fm_sb->magic);
fm_sb->data_crc = bswap32(fm_sb->data_crc);
fm_sb->used_blocks = bswap32(fm_sb->used_blocks);
for(i=0; i < UBI_FM_MAX_BLOCKS; i++)
fm_sb->block_loc[i] = bswap32(fm_sb->block_loc[i]);
for(i=0; i < UBI_FM_MAX_BLOCKS; i++)
fm_sb->block_ec[i] = bswap32(fm_sb->block_ec[i]);
fm_sb->sqnum = bswap64(fm_sb->sqnum);
} else
memset(fm_sb, 0, sizeof(*fm_sb));
}
/* Set logical block at physical. */
static int eba_map[1920];
static int pba_map[1920];
static void usage(char *name)
{
printf("Usage: %s -b [erase block size] -e -v <ubi file> \n", name);
printf("Where,\n -e is dump the logic to physical block map.\n");
printf(" -v is dump the VID headers.\n");
printf(" -b [size] sets the erase block size (flash dependent).\n");
}
typedef struct fastmap {
struct ubi_fm_sb fm_sb;
struct ubi_fm_hdr hdr;
struct ubi_fm_scan_pool pool1;
struct ubi_fm_scan_pool pool2;
/* Free, Used, Scrub and Erase */
struct ubi_fm_ec ec[0];
/* ... */
/* struct ubi_fm_volhdr vol; */
/* struct ubi_fm_eba eba[0]; */
} fastmap;
int main (int argc, char *argv[])
{
int fd, i, erase_block = 0, eba_flag = 0;
int c;
struct ubi_ec_hdr ec;
struct ubi_vid_hdr vid;
int erase_size = 0x20000;
int leb_size;
off_t cur_ec = 0;
int vidless_blocks = 0;
while ((c = getopt (argc, argv, "hveb:")) != -1)
switch (c)
{
case 'h': /* Help */
usage(argv[0]);
goto out;
case 'b':
erase_size = atoi(optarg);
break;
case 'e':
eba_flag = 1;
break;
case 'v':
dump_vid = 1;
break;
case '?':
if (optopt == 'b')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
goto out;
}
if(optind >= argc) {
usage(argv[0]);
goto out;
}
fd = open(argv[optind], O_RDONLY);
if(fd < 0) {
printf("Bad file: %s\n", argv[1]);
goto out;
}
memset(eba_map, -1, sizeof(eba_map));
memset(pba_map, -1, sizeof(pba_map));
/* Process each 'erase block'. */
read_ec(fd,&ec);
while(ec.magic == UBI_EC_HDR_MAGIC) {
leb_size = erase_size - ec.data_offset;
print_ec(&ec);
/* VID present? */
if(lseek(fd, ec.vid_hdr_offset-sizeof(ec), SEEK_CUR) == -1) {
printf("Seek error: %s\n", argv[1]);
goto out;
}
if(read_vid(fd,&vid) != sizeof(vid)) {
printf("File too small: %s\n", argv[1]);
goto out;
}
if(vid.magic == UBI_VID_HDR_MAGIC) {
print_vid(erase_block, &vid);
if(vid.vol_id == 3) {
if(eba_map[vid.lnum] != -1)
printf("EBA dup: %d %d\n", eba_map[vid.lnum], erase_block);
eba_map[vid.lnum] = erase_block;
}
pba_map[erase_block] = vid.lnum;
/* Read volume table. */
if(vid.vol_id == UBI_INTERNAL_VOL_START) {
/* Seek to PEB data offset. */
if(lseek(fd,
ec.data_offset - ec.vid_hdr_offset - sizeof(vid),
SEEK_CUR) == -1)
printf("Seek error: %s\n", argv[1]);
else {
int i;
struct ubi_vtbl_record vtbl;
for(i = 0; i < UBI_MAX_VOLUMES; i++) {
read_vtbl(fd, &vtbl);
if(vtbl.reserved_pebs ||
vtbl.name_len ||
strcmp((char*)vtbl.name, "") != 0) {
printf("VTBL %d\n", i);
print_vtbl(&vtbl);
}
}
}
} else if(vid.vol_id == UBI_FM_SB_VOLUME_ID) {
printf("Found Fastmap super block #PEB %d.\n", erase_block);
if(lseek(fd,
ec.data_offset - ec.vid_hdr_offset - sizeof(vid),
SEEK_CUR) == -1)
printf("Seek error: %s\n", argv[1]);
else {
void *data = alloca(leb_size);
struct ubi_fm_sb *fm_sb = data;
read_fm_sb(fd, data);
print_fm_sb(fm_sb);
}
} else if(vid.vol_id == UBI_FM_DATA_VOLUME_ID) {
printf("Found Fastmap data block #PEB %d.\n", erase_block);
printf("UNSUPPORTED!!!\n");
}
} else if(vid.magic != 0xffffffff){
printf("VID %d corrupt! %x\n", erase_block, vid.magic);
} else {
vidless_blocks++;
}
erase_block++;
cur_ec += erase_size;
cur_ec = lseek(fd, cur_ec, SEEK_SET);
/* Process Erase counter. */
read_ec(fd,&ec);
}
printf("Found %d vidless (free) blocks.\n", vidless_blocks);
if(eba_flag) {
printf("Logical to physical.\n");
for(i = 0; i < ALEN(eba_map); i+=8)
printf("%4d: %4d %4d %4d %4d %4d %4d %4d %4d"
" %4d %4d %4d %4d %4d %4d %4d %4d\n", i,
eba_map[i], eba_map[i+1],
eba_map[i+2], eba_map[i+3],
eba_map[i+4], eba_map[i+5],
eba_map[i+6], eba_map[i+7],
eba_map[i+8], eba_map[i+9],
eba_map[i+10], eba_map[i+11],
eba_map[i+12], eba_map[i+13],
eba_map[i+14], eba_map[i+15]);
printf("Physical to logical.\n");
for(i = 0; i < ALEN(pba_map); i+=8)
printf("%4d: %4d %4d %4d %4d %4d %4d %4d %4d"
" %4d %4d %4d %4d %4d %4d %4d %4d\n", i,
pba_map[i], pba_map[i+1],
pba_map[i+2], pba_map[i+3],
pba_map[i+4], pba_map[i+5],
pba_map[i+6], pba_map[i+7],
pba_map[i+8], pba_map[i+9],
pba_map[i+10], pba_map[i+11],
pba_map[i+12], pba_map[i+13],
pba_map[i+14], pba_map[i+15]);
}
out:
return 0;
}
To build copy ubi-media.h from the UBI directory and run gcc -Wall -g -o parse_ubi parse_ubi.c. The code probably has issues on big-endian platforms; it is also not test with 2.6.28 but I believe it should work as the UBI structures shouldn't change. You may have to remove some fastmap code, if it doesn't compile. The code should give some indication on what is wrong with PEB#1074. Make a copy of the partition when failing and use the code above to analyze the UBI layer.
It is quite possible that the MTD driver does something abnormal which prevents UBI from attaching to an MTD partition. This in-turn prevents UbiFS from mounting. If you know what MTD Nand flash controller is being used, it would help others determine where the issue is.
It can be caused by MTD bugs and/or hardware bugs or UBI/UbiFS issues. If it is UBI/UbiFs, there are backport trees and newer 3.0. You can try to steal the patches from 2.6.32; after applying all, add the 3.0.
Again, the issue can be the MTD driver. Grab MTD changes for your particular CPU/SOCs NAND flash controller. I do this from the mainline; some changes are bug fixes and others infra-structure. You have to look at each patch individually
I am trying to implement user space usb driver using libusb1.0.9. I have lpc2148 blueboard(ARM7) with me..This board is loaded with opensource USB stack/firmware by Mr. Bertrik Sikken. Now my user space driver is trying read write with board. I am getting garbage data.
I want to know about the flow of bulk tranfer.
For any transfer/transaction is there kernel device driver involved??
and do we need usb gadget device driver also??
I am not able to understand that where the data gets copied.
Important thing is that when I read/write interrupt gets generated and I can see correct data on LCD. Do I need to read/write USBRxData/USBTxData?
Please do the needfull.
I tried the below code for bulk transfer read and write..
int usb_read(struct libusb_device *dev,struct libusb_device_handle *hDevice)
{
char *data,*data1;
struct libusb_endpoint_descriptor *ep;
struct libusb_interface_descriptor *id;
int len=64,r,ret_alt,ret_clm,ret_rst,i;
struct libusb_device **list;
data = (char *)malloc(512); //allocation of buffers
data1 = (char *)malloc(512);
memset(data,'\0',512);
memset(data1,'\0',512);
if(hDevice==NULL)
{
printf("\nNO device found\n");
return 0;
}
int ret_open = libusb_open(dev,&hDevice);
if(ret_open!=0)
{
printf("Error in libusb_open\n");
libusb_free_device_list(list,1);
return -1;
}
char str_tx[512]="G"; //data to send to device
char str_rx[512]; //receive string
data = str_tx;
printf("data::%s\t,str::%s\n",data,str_tx);
//printf("%c\n",data);
ep = active_config(dev,hDevice);
printf("after ep\n");
//printf("alt_interface = %d\n",alt_interface);
ret_rst = libusb_reset_device(hDevice);
if(ret_rst < 0)
{
printf("Error in reset :: %d",ret_rst);
return -1;
}
printf("original data1 : %s\n",data1);
r = libusb_bulk_transfer(hDevice,0x08,str_tx,512,&len,0);
//write to device buffer from data
printf("Error number :: %d\n",r);
int le = ep->bEndpointAddress;
int ty = ep->bDescriptorType;
int y = ep->bmAttributes;
printf("y::%d\tatt:: %d\n",y,ep->bmAttributes);
if(r==-1)
printf("Error in io\n");
if(r==0)
{
printf("data returned :: %s\n",data);
printf("len= %d\n",len);
printf("Device Button Pressed!!!!\n");
}
else
{
printf("Error in bulk transfer\n");
return -1;
}
r = libusb_bulk_transfer(hDevice,0x82,data1,512,&len,0);
//read from device buffer to data1
//str_rx = data1;
//printf("End point address::%d\n",le);
//printf("End point desc.type::%d\n",ty);
if(r==-1)
printf("Error in io\n");
if(r==0)
{
printf("data1 returned::%s\n",data1); //received string in data1
printf("len= %d\n",len);
printf("Device Button Pressed!!!!\n");
}
else
{
printf("Error in bulk transfer\n");
return -1;
}
return 0;
}
Try the code given below and it should work on lpc2148.
I have tested this with a lpc2148 configured to receive an interrupt from USB after a write happens (from user-space) and RTC starts running.
Answering to your question whether it involves kernel driver in read/write or not, as far as I have studied, You have to detach the kernel driver and claim the interface using libusb APIs. Though I am not sure whether it can be done without detaching it or not.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include </usr/local/include/libusb-1.0/libusb.h>
#define BULK_EP_OUT 0x82
#define BULK_EP_IN 0x08
int interface_ref = 0;
int alt_interface,interface_number;
int print_configuration(struct libusb_device_handle *hDevice,struct libusb_config_descriptor *config)
{
char *data;
int index;
data = (char *)malloc(512);
memset(data,0,512);
index = config->iConfiguration;
libusb_get_string_descriptor_ascii(hDevice,index,data,512);
printf("\nInterface Descriptors: ");
printf("\n\tNumber of Interfaces : %d",config->bNumInterfaces);
printf("\n\tLength : %d",config->bLength);
printf("\n\tDesc_Type : %d",config->bDescriptorType);
printf("\n\tConfig_index : %d",config->iConfiguration);
printf("\n\tTotal length : %lu",config->wTotalLength);
printf("\n\tConfiguration Value : %d",config->bConfigurationValue);
printf("\n\tConfiguration Attributes : %d",config->bmAttributes);
printf("\n\tMaxPower(mA) : %d\n",config->MaxPower);
free(data);
data = NULL;
return 0;
}
struct libusb_endpoint_descriptor* active_config(struct libusb_device *dev,struct libusb_device_handle *handle)
{
struct libusb_device_handle *hDevice_req;
struct libusb_config_descriptor *config;
struct libusb_endpoint_descriptor *endpoint;
int altsetting_index,interface_index=0,ret_active;
int i,ret_print;
hDevice_req = handle;
ret_active = libusb_get_active_config_descriptor(dev,&config);
ret_print = print_configuration(hDevice_req,config);
for(interface_index=0;interface_index<config->bNumInterfaces;interface_index++)
{
const struct libusb_interface *iface = &config->interface[interface_index];
for(altsetting_index=0;altsetting_index<iface->num_altsetting;altsetting_index++)
{
const struct libusb_interface_descriptor *altsetting = &iface->altsetting[altsetting_index];
int endpoint_index;
for(endpoint_index=0;endpoint_index<altsetting->bNumEndpoints;endpoint_index++)
{
const struct libusb_endpoint_desriptor *ep = &altsetting->endpoint[endpoint_index];
endpoint = ep;
alt_interface = altsetting->bAlternateSetting;
interface_number = altsetting->bInterfaceNumber;
}
printf("\nEndPoint Descriptors: ");
printf("\n\tSize of EndPoint Descriptor : %d",endpoint->bLength);
printf("\n\tType of Descriptor : %d",endpoint->bDescriptorType);
printf("\n\tEndpoint Address : 0x0%x",endpoint->bEndpointAddress);
printf("\n\tMaximum Packet Size: %x",endpoint->wMaxPacketSize);
printf("\n\tAttributes applied to Endpoint: %d",endpoint->bmAttributes);
printf("\n\tInterval for Polling for data Tranfer : %d\n",endpoint->bInterval);
}
}
libusb_free_config_descriptor(NULL);
return endpoint;
}
int main(void)
{
int r = 1;
struct libusb_device **devs;
struct libusb_device_handle *handle = NULL, *hDevice_expected = NULL;
struct libusb_device *dev,*dev_expected;
struct libusb_device_descriptor desc;
struct libusb_endpoint_descriptor *epdesc;
struct libusb_interface_descriptor *intdesc;
ssize_t cnt;
int e = 0,config2;
int i = 0,index;
char str1[64], str2[64];
char found = 0;
// Init libusb
r = libusb_init(NULL);
if(r < 0)
{
printf("\nfailed to initialise libusb\n");
return 1;
}
else
printf("\nInit Successful!\n");
// Get a list os USB devices
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0)
{
printf("\nThere are no USB devices on bus\n");
return -1;
}
printf("\nDevice Count : %d\n-------------------------------\n",cnt);
while ((dev = devs[i++]) != NULL)
{
r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
printf("failed to get device descriptor\n");
libusb_free_device_list(devs,1);
libusb_close(handle);
break;
}
e = libusb_open(dev,&handle);
if (e < 0)
{
printf("error opening device\n");
libusb_free_device_list(devs,1);
libusb_close(handle);
break;
}
printf("\nDevice Descriptors: ");
printf("\n\tVendor ID : %x",desc.idVendor);
printf("\n\tProduct ID : %x",desc.idProduct);
printf("\n\tSerial Number : %x",desc.iSerialNumber);
printf("\n\tSize of Device Descriptor : %d",desc.bLength);
printf("\n\tType of Descriptor : %d",desc.bDescriptorType);
printf("\n\tUSB Specification Release Number : %d",desc.bcdUSB);
printf("\n\tDevice Release Number : %d",desc.bcdDevice);
printf("\n\tDevice Class : %d",desc.bDeviceClass);
printf("\n\tDevice Sub-Class : %d",desc.bDeviceSubClass);
printf("\n\tDevice Protocol : %d",desc.bDeviceProtocol);
printf("\n\tMax. Packet Size : %d",desc.bMaxPacketSize0);
printf("\n\tNo. of Configuraions : %d\n",desc.bNumConfigurations);
e = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, (unsigned char*) str1, sizeof(str1));
if (e < 0)
{
libusb_free_device_list(devs,1);
libusb_close(handle);
break;
}
printf("\nManufactured : %s",str1);
e = libusb_get_string_descriptor_ascii(handle, desc.iProduct, (unsigned char*) str2, sizeof(str2));
if(e < 0)
{
libusb_free_device_list(devs,1);
libusb_close(handle);
break;
}
printf("\nProduct : %s",str2);
printf("\n----------------------------------------");
if(desc.idVendor == 0xffff && desc.idProduct == 0x4)
{
found = 1;
break;
}
}//end of while
if(found == 0)
{
printf("\nDevice NOT found\n");
libusb_free_device_list(devs,1);
libusb_close(handle);
return 1;
}
else
{
printf("\nDevice found");
dev_expected = dev;
hDevice_expected = handle;
}
e = libusb_get_configuration(handle,&config2);
if(e!=0)
{
printf("\n***Error in libusb_get_configuration\n");
libusb_free_device_list(devs,1);
libusb_close(handle);
return -1;
}
printf("\nConfigured value : %d",config2);
if(config2 != 1)
{
libusb_set_configuration(handle, 1);
if(e!=0)
{
printf("Error in libusb_set_configuration\n");
libusb_free_device_list(devs,1);
libusb_close(handle);
return -1;
}
else
printf("\nDevice is in configured state!");
}
libusb_free_device_list(devs, 1);
if(libusb_kernel_driver_active(handle, 0) == 1)
{
printf("\nKernel Driver Active");
if(libusb_detach_kernel_driver(handle, 0) == 0)
printf("\nKernel Driver Detached!");
else
{
printf("\nCouldn't detach kernel driver!\n");
libusb_free_device_list(devs,1);
libusb_close(handle);
return -1;
}
}
e = libusb_claim_interface(handle, 0);
if(e < 0)
{
printf("\nCannot Claim Interface");
libusb_free_device_list(devs,1);
libusb_close(handle);
return -1;
}
else
printf("\nClaimed Interface\n");
active_config(dev_expected,hDevice_expected);
// Communicate
char *my_string, *my_string1;
int transferred = 0;
int received = 0;
int length = 0;
my_string = (char *)malloc(nbytes + 1);
my_string1 = (char *)malloc(nbytes + 1);
memset(my_string,'\0',64);
memset(my_string1,'\0',64);
strcpy(my_string,"prasad divesd");
length = strlen(my_string);
printf("\nTo be sent : %s",my_string);
e = libusb_bulk_transfer(handle,BULK_EP_IN,my_string,length,&transferred,0);
if(e == 0 && transferred == length)
{
printf("\nWrite successful!");
printf("\nSent %d bytes with string: %s\n", transferred, my_string);
}
else
printf("\nError in write! e = %d and transferred = %d\n",e,transferred);
sleep(3);
i = 0;
for(i = 0; i < length; i++)
{
e = libusb_bulk_transfer(handle,BULK_EP_OUT,my_string1,64,&received,0); //64 : Max Packet Lenght
if(e == 0)
{
printf("\nReceived: ");
printf("%c",my_string1[i]); //will read a string from lcp2148
sleep(1);
}
else
{
printf("\nError in read! e = %d and received = %d\n",e,received);
return -1;
}
}
e = libusb_release_interface(handle, 0);
libusb_close(handle);
libusb_exit(NULL);
printf("\n");
return 0;
}
To handle kernal detaching.
if(libusb_kernel_driver_active(dev_handle, 0) == 1) //find out if kernel driver is attached
{
cout << "Kernel Driver Active" << endl;
if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
{
cout << "Kernel Driver Detached!" << endl;
}
}