Infinite printing on read command of character device (through cat command) [duplicate] - module

I am working on simple character device driver. I have implemented read and write functions in the module, the problem is when I try to read the device file using cat /dev/devicefile it is going into infinite loop i.e. reading the same data repeatedly. Can someone suggest me any solution to this problem? Below is my driver code.
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/string.h>
#include<asm/uaccess.h>
#include<linux/init.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("character device driver");
MODULE_AUTHOR("Srinivas");
static char msg[100]={0};
static int t;
static int dev_open(struct inode *, struct file *);
static int dev_rls(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *,size_t, loff_t *);
static ssize_t dev_write(struct file *, const char *, size_t,loff_t *);
static struct file_operations fops =
{
.read = dev_read,
.open = dev_open,
.write = dev_write,
.release = dev_rls,
};
static int himodule( void )
{
t = 0;
t = register_chrdev(0, "chardevdriver", &fops);
if (t < 0)
printk(KERN_ALERT"device registration failed\n");
else
printk(KERN_ALERT"device registered successfully\n");
printk(KERN_ALERT"major number is %d", t);
return 0;
}
static void byemodule(void)
{
unregister_chrdev(t, "chardevdriver");
printk(KERN_ALERT"successfully unregistered\n");
}
static int dev_open(struct inode *inod, struct file *fil)
{
printk(KERN_ALERT"inside the dev open");
return 0;
}
static ssize_t dev_read(struct file *filp, char *buff, size_t len, loff_t *off)
{
short count = 0;
while (msg[count] != 0) {
put_user(msg[count], buff++);
count++;
}
return count;
}
static ssize_t dev_write(struct file *filp, const char *buff, size_t len, loff_t *off)
{
short count = 0;
printk(KERN_ALERT"inside write\n");
memset(msg,0,100);
printk(KERN_ALERT" size of len is %zd",len);
while (len > 0) {
msg[count] = buff[count];
len--;
count++;
}
return count;
}
static int dev_rls(struct inode *inod,struct file *fil)
{
printk(KERN_ALERT"device closed\n");
return 0;
}
module_init(himodule);
module_exit(byemodule);

.read function should also correctly process its len and off arguments. The simplest way to implement reading from memory-buffered file is to use simple_read_from_buffer helper:
static ssize_t dev_read(struct file *filp, char *buff, size_t len, loff_t *off)
{
return simple_read_from_buffer(buff, len, off, msg, 100);
}
You can inspect code of that helper (defined in fs/libfs.c) for educational purposes.
BTW, for your .write method you could use simple_write_to_buffer helper.

You are not respecting the buffer size passed into the dev_read function, so you may be invoking undefined behaviour in cat. Try this:
static ssize_t dev_read( struct file *filp, char *buff, size_t len, loff_t *off )
{
size_t count = 0;
printk( KERN_ALERT"inside read %d\n", *off );
while( msg[count] != 0 && count < len )
{
put_user( msg[count], buff++ );
count++;
}
return count;
}

This problem can be solved by correctly setting *off (fourth parameter of my_read()).
You need to return count for the first time and zero from second time onwards.
if(*off == 0) {
while (msg[count] != 0) {
put_user(msg[count], buff++);
count++;
(*off)++;
}
return count;
}
else
return 0;

Related

GNU Radio circular buffer manipulation

I encountered the following error
gr::log :WARN: tpb_thread_body - asynchronous message buffer overflowing, dropping message
Out of serendipity, I ran into this GNU Radio presentation on
Youtube.
The presenter mentioned an OOT block he called "buffer" that is capable of eliminating the "buffer overflowing" error. Apparently, this block plays with different sample rates and the so-called "circular buffers". I haven't worked with circular buffers myself. Any ideas on circular buffers or any hints on how to build this buffer block are welcome.
EDIT
Below is the flowgraph that generates the error. As it was suggested in the comments, the culprits could be the message processing blocks (red-circled) namely generateCADU (for generating standard CCSDS frames) and processCADU (for extracting CADUs from a data stream).
The implementation file of the generateCADU block is given below
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "generateCADU_impl.h"
#include "fec/ReedSolomon/ReedSolomon.h"
#include "fec/Scrambler/Scrambler.h"
namespace gr {
namespace ccsds {
generateCADU::sptr
generateCADU::make(int frameLength,std::string sync, int scramble, int rs, int intDepth)
{
return gnuradio::get_initial_sptr
(new generateCADU_impl(frameLength, sync, scramble, rs, intDepth));
}
/*
* The private constructor
*/
generateCADU_impl::generateCADU_impl(int frameLength,std::string sync, int scramble, int rs, int intDepth)
: gr::sync_block("generateCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(0, 0, 0)),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
set_output_multiple(d_frameLength);
//Registering output port
message_port_register_out(pmt::mp("out"));
d_sync = parse_string(sync);
}
/*
* Our virtual destructor.
*/
generateCADU_impl::~generateCADU_impl()
{
}
unsigned char
generateCADU_impl::parse_hex(char c)
{
if ('0' <= c && c <= '9') return c - '0';
if ('A' <= c && c <= 'F') return c - 'A' + 10;
if ('a' <= c && c <= 'f') return c - 'a' + 10;
std::abort();
}
std::vector<unsigned char>
generateCADU_impl::parse_string(const std::string & s)
{
if (s.size() % 2 != 0) std::abort();
std::vector<unsigned char> result(s.size() / 2);
for (std::size_t i = 0; i != s.size() / 2; ++i)
result[i] = 16 * parse_hex(s[2 * i]) + parse_hex(s[2 * i + 1]);
return result;
}
int
generateCADU_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
//Reed-Solomon and Scrambler objects
ReedSolomon RS(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
Scrambler S;
//Buffers
unsigned char *frameBuffer1 = (unsigned char*)malloc(d_frameLength*sizeof(unsigned char));
std::vector<unsigned char> frameBuffer2;
//The work function engine
for(int i = 0; (i + d_frameLength) < noutput_items; i += d_frameLength)
{
//Copying data from input stream
memcpy(frameBuffer1,in + i + d_frameLength,d_frameLength);
//Copying frame into std::vector buffer
frameBuffer2.insert(frameBuffer2.begin(),frameBuffer1, frameBuffer1 + d_frameLength);
//Optional scrambling and Reed-Solomon
if (d_rs) RS.Encode_RS(frameBuffer2);
if (d_scramble) S.Scramble(frameBuffer2);
//Insert sync word
frameBuffer2.insert(frameBuffer2.begin(), d_sync.begin(), d_sync.end());
//Transmitting PDU
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer2.data(),frameBuffer2.size())));
message_port_pub(pmt::mp("out"), pdu);
//Clear buffer
frameBuffer2.clear();
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace ccsds */
} /* namespace gr */
And here is the processCADU block. This block uses tags generated by the synchronizeCADU (which is simply a wrapper for the correlate_access_tag block) to extract CADUs
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "processCADU_impl.h"
#include "fec/ReedSolomon/ReedSolomon.h"
#include "fec/Scrambler/Scrambler.h"
namespace gr {
namespace ccsds {
processCADU::sptr
processCADU::make(int frameLength, int scramble, int rs, int intDepth, std::string tagName)
{
return gnuradio::get_initial_sptr
(new processCADU_impl(frameLength, scramble, rs, intDepth, tagName));
}
/*
* The private constructor
*/
processCADU_impl::processCADU_impl(int frameLength, int scramble, int rs, int intDepth, std::string tagName)
: gr::sync_block("processCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(0, 0, 0)),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
//Multiple input
set_output_multiple(d_frameLength * 8);
//Registering output port
message_port_register_out(pmt::mp("out"));
if (d_rs) d_frameLength += 32 * d_intDepth;
//SEtting tag name
key = pmt::mp(tagName);
}
/*
* Our virtual destructor.
*/
processCADU_impl::~processCADU_impl()
{
delete d_pack;
}
int
processCADU_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
unsigned char *out = (unsigned char *) output_items[0];
void *msg_data = NULL;
unsigned char frame_data[d_frameLength];
unsigned char frame_len = 0;
std::vector<unsigned char> frameBuffer;
//Reed-Solomon and Scrambler objects
ReedSolomon RS(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
std::vector<int> errors;//errors.push_back(0);
Scrambler S;
d_tags.clear();
d_pack = new blocks::kernel::pack_k_bits(8);
this->get_tags_in_window(d_tags, 0, 0, noutput_items,key);
for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++) {
// Check that we have enough data for a full frame
if ((d_tags_itr->offset - this->nitems_read(0)) > (noutput_items - (d_frameLength) * 8))
{
return (d_tags_itr->offset - this->nitems_read(0) - 1);
}
//Pack bits into bytes
d_pack->pack(frame_data, &in[d_tags_itr->offset - this->nitems_read(0)], d_frameLength);
//Copying frame into std::vector buffer
frameBuffer.insert(frameBuffer.begin(),frame_data, frame_data + d_frameLength);
//Optional scrambling and Reed-Solomon
if (d_scramble) S.Scramble(frameBuffer);
//if (d_rs) RS.Decode_RS(frameBuffer,errors);
//If there is Reed-Solomon decoding
if(d_rs)
{
RS.Decode_RS(frameBuffer,errors);
if (RS.Success(errors)) // Success
{
//std::cout << "Success" << std::endl;
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer.data(),frameBuffer.size())));
message_port_pub(pmt::mp("out"), pdu);
/*for(int i=0; i < errors.size(); i++)
{
//std::cout << "Number of Errors : " << errors.at(i) << std::endl << std::endl;
}*/
}
else // Failure
{
std::cout << "RS failure" << std::endl;
}
}
else{
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer.data(),frameBuffer.size())));
message_port_pub(pmt::mp("out"), pdu);
}
//Clear buffers
frameBuffer.clear();
errors.clear();
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace ccsds */
} /* namespace gr */
Regards,
M
Thanks to #MarcusMüller suggestion, using the tagged_stream paradigma as opposed to PDUs solved the problem. I was able to transmit 47 terabytes of data without any problems. Below is the code for the newly implemented block.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "genCADU_impl.h"
namespace gr {
namespace ccsds {
genCADU::sptr
genCADU::make(int frameLength,std::string sync, int scramble, int rs, int intDepth, std::string len_tag_key)
{
return gnuradio::get_initial_sptr
(new genCADU_impl(frameLength, sync, scramble, rs, intDepth, len_tag_key));
}
/*
* The private constructor
*/
genCADU_impl::genCADU_impl(int frameLength,std::string sync, int scramble, int rs, int intDepth, std::string len_tag_key)
: gr::tagged_stream_block("genCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(1, 1, sizeof(unsigned char)),len_tag_key),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
//Synchronization pattern
d_sync = parse_string(sync);
//Reed-Solomon and Scrambler objects
RS = new ReedSolomon(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
S = new Scrambler();
}
/*
* Our virtual destructor.
*/
genCADU_impl::~genCADU_impl()
{
delete RS;
delete S;
}
int
genCADU_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
{
int noutput_items = (d_rs) ? d_frameLength + 32*d_intDepth + d_sync.size() : d_frameLength + d_sync.size();
return noutput_items ;
}
unsigned char
genCADU_impl::parse_hex(char c)
{
if ('0' <= c && c <= '9') return c - '0';
if ('A' <= c && c <= 'F') return c - 'A' + 10;
if ('a' <= c && c <= 'f') return c - 'a' + 10;
std::abort();
}
std::vector<unsigned char>
genCADU_impl::parse_string(const std::string & s)
{
if (s.size() % 2 != 0) std::abort();
std::vector<unsigned char> result(s.size() / 2);
for (std::size_t i = 0; i != s.size() / 2; ++i)
result[i] = 16 * parse_hex(s[2 * i]) + parse_hex(s[2 * i + 1]);
return result;
}
int
genCADU_impl::work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
unsigned char *out = (unsigned char *) output_items[0];
int total_len;
//Copy pdu from circular buffer to local buffer
buffer.insert(buffer.end(), in, in + d_frameLength);
//Optional scrambling and Reed-Solomon. TO DO: Turbo and LDPC
if (d_rs) RS->Encode_RS(buffer);
if (d_scramble) S->Scramble(buffer);
//Insert sync word
buffer.insert(buffer.begin(), d_sync.begin(), d_sync.end());
//Copy from local buffer to circular buffer
std::copy(buffer.begin(),buffer.end(),out);
//Clear the local buffer
total_len = buffer.size();
buffer.clear();
// Tell runtime system how many output items we produced.
return total_len;
}
} /* namespace ccsds */
} /* namespace gr */
Regards,
M.

calling Objective C and C from Swift passing callback function

I am trying to call the HappyTime onvif library from Swift.
I have the library linked in to my project and I am able to call some simple functions, but I am having trouble getting the syntax right in my call which passes my callback function.
Here is the Swift code:
func discoverCameras()
{
HappyInterface.sharedInstance().startProb()
//this line gives syntax error
HappyInterface.sharedInstance().setProbeCB(cameraDiscovered)
}
func cameraDiscovered(cameraFound:UnsafeMutablePointer<DEVICE_BINFO>)
{
table.reloadData()
}
my setProbeCB call gives this error:
Cannot convert value of type '(UnsafeMutablePointer) -> ()' to expected argument type 'UnsafeMutablePointer' (aka 'UnsafeMutablePointer, UnsafeMutablePointer<()>) -> ()>>')
Here is the Obj C implementation:
- (void) setProbeCB:(onvif_probe_cb *)cb {
set_probe_cb(*cb, 0);
}
This is the Obj C header:
- (void) setProbeCB:(onvif_probe_cb *)cb;
This is the C header:
#ifndef __H_ONVIF_PROBE_H__
#define __H_ONVIF_PROBE_H__
#include "onvif.h"
typedef void (* onvif_probe_cb)(DEVICE_BINFO * p_res, void * pdata);
#ifdef __cplusplus
extern "C" {
#endif
ONVIF_API void set_probe_cb(onvif_probe_cb cb, void * pdata);
ONVIF_API void set_probe_interval(int interval);
ONVIF_API int start_probe(int interval);
ONVIF_API void stop_probe();
ONVIF_API void send_probe_req();
#ifdef __cplusplus
}
#endif
#endif // __H_ONVIF_PROBE_H__
This is the C code:
/***************************************************************************************/
#define MAX_PROBE_FD 8
/***************************************************************************************/
onvif_probe_cb g_probe_cb = 0;
void * g_probe_cb_data = 0;
pthread_t g_probe_thread = 0;
int g_probe_fd[MAX_PROBE_FD];
int g_probe_interval = 30;
BOOL g_probe_running = FALSE;
/***************************************************************************************/
int onvif_probe_init(unsigned int ip)
{
int opt = 1;
SOCKET fd;
struct sockaddr_in addr;
struct ip_mreq mcast;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if(fd < 0)
{
log_print(LOG_ERR, "socket SOCK_DGRAM error!\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(3702);
addr.sin_addr.s_addr = ip;
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
// if port 3702 already occupied, only receive unicast message
addr.sin_port = 0;
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
closesocket(fd);
log_print(LOG_ERR, "bind error! %s\n", sys_os_get_socket_error());
return -1;
}
}
/* reuse socket addr */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)))
{
log_print(LOG_WARN, "setsockopt SO_REUSEADDR error!\n");
}
memset(&mcast, 0, sizeof(mcast));
mcast.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
mcast.imr_interface.s_addr = ip;
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mcast, sizeof(mcast)) < 0)
{
#if __WIN32_OS__
if(setsockopt(fd, IPPROTO_IP, 5, (char*)&mcast, sizeof(mcast)) < 0)
#endif
{
closesocket(fd);
log_print(LOG_ERR, "setsockopt IP_ADD_MEMBERSHIP error! %s\n", sys_os_get_socket_error());
return -1;
}
}
return fd;
}
char probe_req1[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<Envelope xmlns:tds=\"http://www.onvif.org/ver10/device/wsdl\" xmlns=\"http://www.w3.org/2003/05/soap-envelope\">"
"<Header>"
"<wsa:MessageID xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">uuid:%s</wsa:MessageID>"
"<wsa:To xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To>"
"<wsa:Action xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action>"
"</Header>"
"<Body>"
"<Probe xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\">"
"<Types>tds:Device</Types>"
"<Scopes />"
"</Probe>"
"</Body>"
"</Envelope>";
char probe_req2[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<Envelope xmlns:dn=\"http://www.onvif.org/ver10/network/wsdl\" xmlns=\"http://www.w3.org/2003/05/soap-envelope\">"
"<Header>"
"<wsa:MessageID xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">uuid:%s</wsa:MessageID>"
"<wsa:To xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To>"
"<wsa:Action xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action>"
"</Header>"
"<Body>"
"<Probe xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\">"
"<Types>dn:NetworkVideoTransmitter</Types>"
"<Scopes />"
"</Probe>"
"</Body>"
"</Envelope>";
int onvif_probe_req_tx(int fd)
{
int len;
int rlen;
char * p_bufs = NULL;
struct sockaddr_in addr;
int buflen = 10*1024;
p_bufs = (char *)malloc(buflen);
if (NULL == p_bufs)
{
return -1;
}
memset(p_bufs, 0, buflen);
sprintf(p_bufs, probe_req1, onvif_uuid_create());
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("239.255.255.250");
addr.sin_port = htons(3702);
len = strlen(p_bufs);
rlen = sendto(fd, p_bufs, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if (rlen != len)
{
log_print(LOG_ERR, "onvif_probe_req_tx::rlen = %d,slen = %d\r\n", rlen, len);
}
usleep(1000);
memset(p_bufs, 0, buflen);
sprintf(p_bufs, probe_req2, onvif_uuid_create());
len = strlen(p_bufs);
rlen = sendto(fd, p_bufs, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if (rlen != len)
{
log_print(LOG_ERR, "onvif_probe_req_tx::rlen = %d,slen = %d\r\n", rlen, len);
}
free(p_bufs);
return rlen;
}
BOOL onvif_parse_device_binfo(XMLN * p_node, DEVICE_BINFO * p_res)
{
XMLN * p_EndpointReference;
XMLN * p_Types;
XMLN * p_XAddrs;
p_EndpointReference = xml_node_soap_get(p_node, "EndpointReference");
if (p_EndpointReference)
{
XMLN * p_Address = xml_node_soap_get(p_EndpointReference, "Address");
if (p_Address && p_Address->data)
{
strncpy(p_res->EndpointReference, p_Address->data, sizeof(p_res->EndpointReference)-1);
}
}
p_Types = xml_node_soap_get(p_node, "Types");
if (p_Types && p_Types->data)
{
p_res->type = parse_DeviceType(p_Types->data);
}
p_XAddrs = xml_node_soap_get(p_node, "XAddrs");
if (p_XAddrs && p_XAddrs->data)
{
parse_XAddr(p_XAddrs->data, &p_res->XAddr);
if (p_res->XAddr.host[0] == '\0' || p_res->XAddr.port == 0)
{
return FALSE;
}
}
else
{
return FALSE;
}
return TRUE;
}
BOOL onvif_probe_res(XMLN * p_node, DEVICE_BINFO * p_res)
{
XMLN * p_body = xml_node_soap_get(p_node, "Body");
if (p_body)
{
XMLN * p_ProbeMatches = xml_node_soap_get(p_body, "ProbeMatches");
if (p_ProbeMatches)
{
XMLN * p_ProbeMatch = xml_node_soap_get(p_ProbeMatches, "ProbeMatch");
while (p_ProbeMatch && soap_strcmp(p_ProbeMatch->name, "ProbeMatch") == 0)
{
if (onvif_parse_device_binfo(p_ProbeMatch, p_res))
{
if (g_probe_cb)
{
g_probe_cb(p_res, g_probe_cb_data);
}
}
p_ProbeMatch = p_ProbeMatch->next;
}
}
else
{
XMLN * p_Hello = xml_node_soap_get(p_body, "Hello");
if (p_Hello)
{
if (onvif_parse_device_binfo(p_Hello, p_res))
{
if (g_probe_cb)
{
g_probe_cb(p_res, g_probe_cb_data);
}
}
}
}
}
return TRUE;
}
int onvif_probe_net_rx()
{
int i;
int ret;
int maxfd = 0;
int fd = 0;
char rbuf[10*1024];
fd_set fdread;
struct timeval tv = {1, 0};
FD_ZERO(&fdread);
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
FD_SET(g_probe_fd[i], &fdread);
if (g_probe_fd[i] > maxfd)
{
maxfd = g_probe_fd[i];
}
}
}
ret = select(maxfd+1, &fdread, NULL, NULL, &tv);
if (ret == 0) // Time expired
{
return 0;
}
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0 && FD_ISSET(g_probe_fd[i], &fdread))
{
int rlen;
int addr_len;
struct sockaddr_in addr;
unsigned int src_ip;
unsigned int src_port;
XMLN * p_node;
fd = g_probe_fd[i];
addr_len = sizeof(struct sockaddr_in);
rlen = recvfrom(fd, rbuf, sizeof(rbuf), 0, (struct sockaddr *)&addr, (socklen_t*)&addr_len);
if (rlen <= 0)
{
log_print(LOG_ERR, "onvif_probe_net_rx::rlen = %d, fd = %d\r\n", rlen, fd);
continue;
}
src_ip = addr.sin_addr.s_addr;
src_port = addr.sin_port;
p_node = xxx_hxml_parse(rbuf, rlen);
if (p_node == NULL)
{
log_print(LOG_ERR, "onvif_probe_net_rx::hxml parse err!!!\r\n");
}
else
{
DEVICE_BINFO res;
memset(&res, 0, sizeof(DEVICE_BINFO));
onvif_probe_res(p_node, &res);
}
xml_node_del(p_node);
}
}
return 1;
}
void * onvif_probe_thread(void * argv)
{
int count = 0;
int i = 0;
int j = 0;
for (; i < get_if_nums() && j < MAX_PROBE_FD; i++, j++)
{
unsigned int ip = get_if_ip(i);
if (ip != 0 && ip != inet_addr("127.0.0.1"))
{
g_probe_fd[j] = onvif_probe_init(ip);
}
}
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
onvif_probe_req_tx(g_probe_fd[i]);
}
}
while (g_probe_running)
{
if (onvif_probe_net_rx() == 0)
{
count++;
}
if (count >= g_probe_interval)
{
count = 0;
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
onvif_probe_req_tx(g_probe_fd[i]);
}
}
}
usleep(1000);
}
g_probe_thread = 0;
return NULL;
}
ONVIF_API void set_probe_cb(onvif_probe_cb cb, void * pdata)
{
g_probe_cb = cb;
g_probe_cb_data = pdata;
}
ONVIF_API void send_probe_req()
{
int i;
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
onvif_probe_req_tx(g_probe_fd[i]);
}
}
}
ONVIF_API void set_probe_interval(int interval)
{
g_probe_interval = interval;
if (g_probe_interval < 10)
{
g_probe_interval = 30;
}
}
ONVIF_API int start_probe(int interval)
{
g_probe_running = TRUE;
set_probe_interval(interval);
g_probe_thread = sys_os_create_thread((void *)onvif_probe_thread, NULL);
if (g_probe_thread)
{
return 0;
}
return -1;
}
ONVIF_API void stop_probe()
{
int i;
g_probe_running = FALSE;
while (g_probe_thread)
{
usleep(1000);
}
for (i = 0; i < MAX_PROBE_FD; i++)
{
if (g_probe_fd[i] > 0)
{
closesocket(g_probe_fd[i]);
g_probe_fd[i] = 0;
}
}
}
Here is what the DEVICE_BINFO struct looks like:
typedef struct
{
int type; // device type
char EndpointReference[100];
onvif_XAddr XAddr; // xaddr, include port host, url
} DEVICE_BINFO;
One thing that should be fixed is a mismatch in the number of arguments to the callback. Swift calls the Objective-C setProbeCB() method, giving it a pointer to the cameraDiscovered() function, which takes a single argument. Then setProbeCB() gives the function pointer to the C set_probe_cb() function, which expects a pointer to a function that takes two arguments.
Another observation is that setProbeCB() could just take onvif_probe_cb instead of onvif_probe_cb* and then call C code simply as set_probe_cb(cb, 0). However, I don't think it makes much difference.
Also, I think the question could have been distilled to a smaller size.
The following is a simplified example based on your original code. It shows how to implement a callback in Swift and have C code call it, but the real fun starts when passing data via callback parameters and return values. It gets very tricky very fast, and that's why the example doesn't show how to deal with DEVICE_BINFO in Swift code. It's a topic in its own right.
The clue to using (Objective-)C functions and types in Swift is figuring out how they are imported into Swift. For example, to find out how onvif_probe_cb is imported, type it on a line in the Swift code, place the cursor in it, and Quick Help will show you this:
Declaration: typealias onvif_probe_cb = (UnsafeMutablePointer<DEVICE_BINFO>, UnsafeMutablePointer<Void>) -> Void
Declared in: clib.h
That tells us the parameter and return types to use in our Swift implementation of the callback.
The example is by no means production quality: there are all kinds of things that can go haywire in terms of memory management etc. Please see the code comments for additional info.
First, here is the C code header (clib.h):
#ifndef clib_h
#define clib_h
#include <stdio.h>
typedef struct {
char hostname[50];
int32_t port;
char url[200];
} onvif_XAddr;
typedef struct
{
int type; // device type
char EndpointReference[100];
onvif_XAddr XAddr; // xaddr, include port host, url
} DEVICE_BINFO;
/**
* This is the typedef of the function pointer to be used for our callback.
* The function takes a pointer to DEVICE_BINFO and a pointer to some arbitrary
* data meaningful to the code that provides the callback implementation. It will
* be NULL in this example.
*/
typedef void (* onvif_probe_cb)(DEVICE_BINFO * p_res, void * pdata);
/**
* A function to set the callback.
*/
void set_probe_cb(onvif_probe_cb cb, void * pdata);
/**
* This is a function that calls the callback.
*/
void find_device();
#endif /* clib_h */
Here is the rest of our C source (clib.c):
#include "clib.h"
#include <string.h>
onvif_probe_cb gCB = 0; // global variable to store the callback pointer
void * gUserData = 0; // global variable to store pointer to user data
DEVICE_BINFO gDeviceInfo; // global variable to store device info struct
void find_device() {
// Set up gDeviceInfo
gDeviceInfo.XAddr.port = 1234;
strcpy( gDeviceInfo.XAddr.hostname, "myhost");
strcpy( gDeviceInfo.XAddr.url, "http://junk.com");
gDeviceInfo.type = 777;
// ... and, if a callback is available, call it with the device info
if (gCB) gCB(&gDeviceInfo, gUserData);
else puts("No callback available");
}
void set_probe_cb(onvif_probe_cb cb, void * pdata) {
gCB = cb;
gUserData = pdata;
}
Here is the Objective-C wrapper header (oclib.h):
#ifndef oclib_h
#define oclib_h
#import "clib.h"
#import <Foundation/Foundation.h>
/**
* Interface of an Objective-C wrapper around C code in clib.*. We could have
* gone straight to C from Swift, but I'm trying to keep the example close to the
* code in the question. Also, this extra Objective C layer could be helpful in
* translating data structures, such as DEVICE_BINFO, between C and Swift, since
* Objective-C plays much nicer with C data types. This is no surprise: any C code
* is valid Objective-C (Objective-C is a strict superset of C).
*/
#interface MyWrapper : NSObject
-(id)init;
// Please note: this one takes a single argument, while the C function it wraps
// takes 2; see the implementation.
-(void) setProbeCB:(onvif_probe_cb) cb;
-(void) findDevice;
#end
#endif /* oclib_h */
And the wrapper implementation (oclib.m):
#import "oclib.h"
/**
* Implementation of our Objective-C wrapper.
*/
#implementation MyWrapper
-(id)init { return self; }
-(void) setProbeCB:(onvif_probe_cb) cb {
// We don't want anything other than device info to be passed back and
// forth via the callback, so this wrapper function takes a single argument
// and passes 0 as the 2nd argument to the wrapped C function.
set_probe_cb(cb, 0);
}
-(void) findDevice {
find_device();
}
#end
Finally, here is the Swift code that implements the callback (main.swift):
var w : MyWrapper = MyWrapper()
/**
* This is the callback implementation in Swift. We don't use the 2nd argument, userData, but it still
* has to be present to satisfy the way the callback function pointer is specified in C code.
*/
func cameraDiscovered( info : UnsafeMutablePointer<DEVICE_BINFO>, userData : UnsafeMutablePointer<Void>) {
print("Called the Swift callback!")
let devInfo : DEVICE_BINFO = info.memory;
print( "The device type is \(devInfo.type)")
print( "The device port is \(devInfo.XAddr.port)")
}
// Provide the callback to C code via Objective-C
w.setProbeCB(cameraDiscovered)
// ... and call a function that will cause the C code to invoke the callback.
w.findDevice()
The bridging header just has #import oclib.h, thus exposing the contents of both C and Objective-C headers to Swift.
The expected output:
Called the Swift callback!
The device type is 777
The device port is 1234

How to remove duplicates from my array of structs?

Here is my code that reads structs from a file.
int _tmain(int argc, _TCHAR* argv[])
{
typedef struct
{
char name_1[100];
char Max_1[100];
char Min_1[100];
} power_line_name;
int numLines;
StreamReader ^ sr1=File::OpenText("testcpp\\test\\powerline.txt");
while(sr1->ReadLine())
{
numLines++;
}
power_line_name* power_list=new power_line_name[numLines];
//power_line_name power_list[5];
StreamReader ^ sr=File::OpenText("testcpp\\test\\powerline.txt");
array<System::String ^> ^power_line;
array<System::String ^> ^d_line;
String ^ eachString;
String ^ eachString_2;
String ^ eachString_3;
int i=0;
char nstring[100];
try
{
String^ s="";
while (s=sr->ReadLine())
{
power_line=s->Split(':');
Console::WriteLine(s);
d_line=power_line[1]->Split('|');
for(int a=0;a<d_line->Length;a++)
{
pin_ptr<const wchar_t> wch = PtrToStringChars(d_line[a]);
size_t origsize = wcslen(wch) + 1;
size_t convertedChars = 0;
if(a==0)
{
wcstombs_s(&convertedChars, power_list[i].name_1, origsize, wch, _TRUNCATE);
strcat_s(power_list[i].name_1, " (char *)");
}
if(a==1)
{
wcstombs_s(&convertedChars, power_list[i].Max_1, origsize, wch, _TRUNCATE);
strcat_s(power_list[i].Max_1, " (char *)");
}
if(a==2)
{
wcstombs_s(&convertedChars, power_list[i].Min_1, origsize, wch, _TRUNCATE);
strcat_s(power_list[i].Min_1, " (char *)");
}
}
i++;
}
Console::WriteLine(s);
}
finally
{
if(sr)
delete (IDisposable^)(sr);
}
return 0;
}
Here is its output:
power_list[0].name_1=aaaa
power_list[0].Max_1=1111111
power_list[0].Min_1=222222
power_list[1].name_1=aaaa
power_list[1].Max_1=333333
power_list[1].Min_1=444444
power_list[2].name_1=aaaa
power_list[2].Max_1=333333
power_list[2].Min_1=444444
power_list[3].name_1=aaaa
power_list[3].Max_1=33333
power_list[3].Min_1=66666
If Max_1 and Min_1 are the same for some two elements, I would like the second element to be removed.
So the new ouput would be:
power_list[0].name_1=aaaa
power_list[0].Max_1=1111111
power_list[0].Min_1=222222
power_list[1].name_1=aaaa
power_list[1].Max_1=333333
power_list[1].Min_1=444444
power_list[2].name_1=aaaa
power_list[2].Max_1=33333
power_list[2].Min_1=66666
i don't know how to do??
I am not familiar with c++-cli syntax, so here is one way to do it, in pseudo-code:
for i from 0 to n-1
for j from i+1 to n-1
if list[i].Max_1 == list[j].Max_1 and list[i].Min_1 == list[j].Min_1
mark j as duplicate
for i from 0 to n-1
if i is not marked duplicate
output i
This seems to be the simplest way to do it.
Another more sophisticated way: sort your array; then all duplicate entries will be adjacent, which will make comparisons easier. Maybe someone else will describe this in another answer.

Convert decimal to binary and return array

probably there is a smart way to do that , but anyway i get error on this :
-(int*)decimalBinary:(int)decimal
{
int i=0;
int *bin;
while (decimal!=0)
{
bin[i]=decimal%2;
decimal=decimal/2;
i++;
}
return bin;
}
on the modulo line . why ?
And whats the better way to get it to array ?
Declaring
int *bin;
sets aside space for a pointer but doesn't make it point to an object. It is crucial to initialize bin before using it.
To solve your problem you can declare an array bin[4] in caller function (int main) and then pass *bin to your calling function.
The following code is adapted from This answer on how to print an integer in binary format. Storing "binary digits" into an int array is added into the code below:
#include <stdio.h> /* printf */
#include <stdlib.h> /* strtol */
const char *byte_to_binary(long x);
int main(void)
{
long lVal;
int i, len, array[18];
char buf[18];
{ /* binary string to int */
char *tmp;
char *b = "11010111001010110";
lVal=strtol(b, &tmp, 2); //convert string in "base 2" format to long int
printf("%d\n", lVal);
}
{
printf("%s", byte_to_binary(lVal));
/* byte to binary string */
sprintf(buf,"%s", byte_to_binary(lVal));
}
len = strlen(buf);
for(i=0;i<len;i++)
{ //store binary digits into an array.
array[i] = (buf[i]-'0');
}
getchar();
return 0;
}
const char *byte_to_binary(long x)
{
static char b[17]; //16 bits plus '\0'
b[0] = '\0';
char *p = b;
int z;
for (z = 65536; z > 0; z >>= 1) //2^16
{
*p++ = (x & z) ? '1' : '0';
}
return b;
}

USB applications using libusb library

I want to use libusb library for writing some test applications for USB.
Can any one please suggest how to set control transfers using usb_control_msg call?
I am getting bad descriptor error while running the following code.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "usb.h"
static int vendor_id;
static int product_id;
typedef struct{
int requesttype;
int request;
int value;
int index;
char *bytes;
int size;
int timeout;
}ctrlmsg_param;
void print_endpoint(struct usb_endpoint_descriptor *endpoint)
{
printf("=====End point Information====\n");
printf("bEndpointAddress: %x\n", endpoint->bEndpointAddress);
printf("bmAttributes: %x\n", endpoint->bmAttributes);
printf("wMaxPacketSize: %d\n", endpoint->wMaxPacketSize);
printf("bInterval: %d\n", endpoint->bInterval);
printf("bRefresh: %d\n", endpoint->bRefresh);
printf("bSynchAddress: %d\n", endpoint->bSynchAddress);
}
void print_altsetting(struct usb_interface_descriptor *interface)
{
int i;
printf("\n=====Alternate Setting Information====\n");
printf("bInterfaceNumber: %d\n", interface->bInterfaceNumber);
printf("bAlternateSetting: %d\n", interface->bAlternateSetting);
printf("bNumEndpoints: %d\n", interface->bNumEndpoints);
printf("bInterfaceClass: %d\n", interface->bInterfaceClass);
printf("bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);
printf("bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);
printf("iInterface: %d\n", interface->iInterface);
for (i = 0; i < interface->bNumEndpoints; i++)
print_endpoint(&interface->endpoint[i]);
}
void print_interface(struct usb_interface *interface)
{
int i;
for (i = 0; i < interface->num_altsetting; i++)
print_altsetting(&interface->altsetting[i]);
}
void print_configuration(struct usb_config_descriptor *config)
{
int i;
printf("=====Configuration Information====\n");
printf("wTotalLength: %d\n", config->wTotalLength);
printf("bNumInterfaces: %d\n", config->bNumInterfaces);
printf("bConfigurationValue: %d\n", config->bConfigurationValue);
printf("iConfiguration: %d\n", config->iConfiguration);
printf("bmAttributes: %x\n", config->bmAttributes);
printf("MaxPower: %d\n", config->MaxPower);
for (i = 0; i < config->bNumInterfaces; i++)
print_interface(&config->interface[i]);
}
int print_device(struct usb_device *dev)
{
usb_dev_handle *udev;
char str[100];
int ret, i;
udev = usb_open(dev);
if (udev) {
if (dev->descriptor.iManufacturer) {
ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, str, sizeof(str));
if (ret > 0)
{
printf("Manufacturer is %s\n",str);
}
}
if (dev->descriptor.iProduct) {
ret = usb_get_string_simple(udev, dev->descriptor.iProduct, str, sizeof(str));
if (ret > 0)
{
printf("Product is %s\n",str);
}
}
}
if (udev)
usb_close(udev);
printf("Possible configurations are %x\n",dev->descriptor.bNumConfigurations);
sleep(2);
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
print_configuration(&dev->config[i]);
return 0;
}
int htod( const char* str )
{
int decimal;
sscanf( str, "%x", &decimal);
return decimal;
}
void set_data(struct usb_device *dev)
{
ctrlmsg_param param;
param.requesttype= 0;
param.request=0;
param.value=0;
param.index=0;
param.bytes=10;
param.size=0;
param.timeout=5000;
usb_control_msg(dev, param.requesttype, param.request, param.value, param.index, param.bytes, param.size, param.timeout);
printf("error is %s\n",strerror(errno));
return;
}
int main(int argc, char *argv[])
{
struct usb_bus *bus;
struct usb_device *dev;
if(argc != 3)
{
printf("Error in number of arguments\n");
printf("Usage:./usb_info <vendor id> <product id>\n");
exit(0);
}
vendor_id=htod(argv[1]);
product_id=htod(argv[2]);
printf("initializing USB library\n");
usb_init();
printf("Finding Buses and Devices\n");
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
if ((dev->descriptor.idProduct == product_id) && (dev->descriptor.idVendor == vendor_id)){
printf("Found device with produxt id %x and vendor id %x\n",product_id,vendor_id);
print_device(dev);
set_data(dev);
print_device(dev);
}
}
}
return 0;
}
Regards,
Sandeep
I think that you mean usb_control_msg() is returns an error code for "bad descriptor". Please clarify if this is incorrect.
USB control transfers have some very specific formatting rules, and if the packet you are forming is sent to any compliant device, it will return a request error / stall on the bus.
You are sending the control transfer:
bmRequestType = 0x00
bRequest = 0x00
wValue = 0x0000
wIndex = 0x0000
wSize = 0x0000
this should be interpreted by the USB device as a GET_STATUS request, so wLength is required to be 2, and bmRequestType needs to have the top bit set, indicating this is an IN direction request (from the host's point of view). This is all from Chapter 9 of the USB specification 1.1/2.0/3.1 available at www.usb.org.
The parameter char *bytes (your param.bytes) also needs to be an address/pointer in the call you are making.
A good standard control transfer to test with would be:
bmRequestType = 0x80
bRequest = 0x06
wValue = 0x0001
wIndex = 0x0000
wSize = 0x0008
This request will return the first 8 bytes of the Device Descriptor, it is valid for every USB device, in all states.
The other transfer types (bulk, interrupt) don't have these strict formatting rules, and can be an easier place to start. I'd imagine you have already moved past this issue, since the question has been posted for quite a while, but maybe this response will still help someone else.