summaryrefslogtreecommitdiff
path: root/pcap-canusb-linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'pcap-canusb-linux.c')
-rw-r--r--pcap-canusb-linux.c361
1 files changed, 200 insertions, 161 deletions
diff --git a/pcap-canusb-linux.c b/pcap-canusb-linux.c
index 5abfe18ec71f6..b84f884cee971 100644
--- a/pcap-canusb-linux.c
+++ b/pcap-canusb-linux.c
@@ -75,20 +75,18 @@ struct CAN_Msg
struct canusb_t
{
- libusb_context *ctx;
- libusb_device_handle *dev;
- char* src;
- pthread_t worker;
- int rdpipe, wrpipe;
- volatile int* loop;
+ libusb_context *ctx;
+ libusb_device_handle *dev;
+ char *serial;
+ pthread_t worker;
+ int rdpipe, wrpipe;
+ volatile int* loop;
};
static struct canusb_t canusb;
static volatile int loop;
-
-
-int canusb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
libusb_context *fdctx;
libusb_device** devs;
@@ -96,8 +94,15 @@ int canusb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
unsigned char buf[96];
int cnt, i;
- libusb_init(&fdctx);
-
+ if (libusb_init(&fdctx) != 0) {
+ /*
+ * XXX - if this doesn't just mean "no USB file system mounted",
+ * perhaps we should report a real error rather than just
+ * saying "no CANUSB devices".
+ */
+ return 0;
+ }
+
cnt = libusb_get_device_list(fdctx,&devs);
for(i=0;i<cnt;i++)
@@ -108,27 +113,27 @@ int canusb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
libusb_get_device_descriptor(devs[i],&desc);
if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID))
- continue; //It is not, check next device
+ continue; //It is not, check next device
//It is!
libusb_device_handle *dh = NULL;
if (ret = libusb_open(devs[i],&dh) == 0)
{
- char dev_name[30];
- char dev_descr[50];
+ char dev_name[30];
+ char dev_descr[50];
int n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,sernum,64);
sernum[n] = 0;
- snprintf(dev_name, 30, CANUSB_IFACE"%s", sernum);
- snprintf(dev_descr, 50, "CanUSB [%s]", sernum);
+ snprintf(dev_name, 30, CANUSB_IFACE"%s", sernum);
+ snprintf(dev_descr, 50, "CanUSB [%s]", sernum);
libusb_close(dh);
if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0)
{
- libusb_free_device_list(devs,1);
- return -1;
+ libusb_free_device_list(devs,1);
+ return -1;
}
}
}
@@ -199,144 +204,176 @@ static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char*
pcap_t *
-canusb_create(const char *device, char *ebuf)
+canusb_create(const char *device, char *ebuf, int *is_ours)
{
- pcap_t* p;
-
- libusb_init(&canusb.ctx);
-
- p = pcap_create_common(device, ebuf);
- if (p == NULL)
- return (NULL);
-
- memset(&canusb, 0x00, sizeof(canusb));
-
-
- p->activate_op = canusb_activate;
-
- canusb.src = strdup(p->opt.source);
- return (p);
+ const char *cp;
+ char *cpend;
+ long devnum;
+ pcap_t* p;
+
+ libusb_init(&canusb.ctx);
+
+ /* Does this look like a DAG device? */
+ cp = strrchr(device, '/');
+ if (cp == NULL)
+ cp = device;
+ /* Does it begin with "canusb"? */
+ if (strncmp(cp, "canusb", 6) != 0) {
+ /* Nope, doesn't begin with "canusb" */
+ *is_ours = 0;
+ return NULL;
+ }
+ /* Yes - is "canusb" followed by a number? */
+ cp += 6;
+ devnum = strtol(cp, &cpend, 10);
+ if (cpend == cp || *cpend != '\0') {
+ /* Not followed by a number. */
+ *is_ours = 0;
+ return NULL;
+ }
+ if (devnum < 0) {
+ /* Followed by a non-valid number. */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ memset(&canusb, 0x00, sizeof(canusb));
+
+ p->activate_op = canusb_activate;
+
+ return (p);
}
static void* canusb_capture_thread(struct canusb_t *canusb)
{
- struct libusb_context *ctx;
- libusb_device_handle *dev;
-
- int i, n;
- struct
- {
- uint8_t rxsz, txsz;
- } status;
+ struct libusb_context *ctx;
+ libusb_device_handle *dev;
+ int i, n;
+ struct
+ {
+ uint8_t rxsz, txsz;
+ } status;
+ char *serial;
- libusb_init(&ctx);
+ libusb_init(&ctx);
- char *serial = canusb->src + strlen(CANUSB_IFACE);
- dev = canusb_opendevice(ctx, serial);
+ serial = canusb->serial;
+ dev = canusb_opendevice(ctx, serial);
- fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK);
+ fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK);
- while(*canusb->loop)
- {
- int sz, ret;
- struct CAN_Msg msg;
+ while(*canusb->loop)
+ {
+ int sz, ret;
+ struct CAN_Msg msg;
- libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
- //HACK!!!!! -> drop buffered data, read new one by reading twice.
- ret = libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
+ libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
+ //HACK!!!!! -> drop buffered data, read new one by reading twice.
+ ret = libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100);
- for(i = 0; i<status.rxsz; i++)
- {
- libusb_bulk_transfer(dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100);
- n = write(canusb->wrpipe, &msg, sizeof(msg));
- }
+ for(i = 0; i<status.rxsz; i++)
+ {
+ libusb_bulk_transfer(dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100);
+ n = write(canusb->wrpipe, &msg, sizeof(msg));
+ }
- }
+ }
- libusb_close(dev);
- libusb_exit(ctx);
+ libusb_close(dev);
+ libusb_exit(ctx);
- return NULL;
+ return NULL;
}
static int canusb_startcapture(struct canusb_t* this)
{
- int pipefd[2];
+ int pipefd[2];
- if (pipe(pipefd) == -1) return -1;
+ if (pipe(pipefd) == -1)
+ return -1;
- canusb.rdpipe = pipefd[0];
- canusb.wrpipe = pipefd[1];
- canusb.loop = &loop;
+ canusb.rdpipe = pipefd[0];
+ canusb.wrpipe = pipefd[1];
+ canusb.loop = &loop;
- loop = 1;
- pthread_create(&this->worker, NULL, canusb_capture_thread, &canusb);
+ loop = 1;
+ pthread_create(&this->worker, NULL, canusb_capture_thread, &canusb);
- return canusb.rdpipe;
+ return canusb.rdpipe;
}
static void canusb_clearbufs(struct canusb_t* this)
{
- unsigned char cmd[16];
- int al;
+ unsigned char cmd[16];
+ int al;
- cmd[0] = 1; //Empty incoming buffer
- cmd[1] = 1; //Empty outgoing buffer
- cmd[3] = 0; //Not a write to serial number
- memset(&cmd[4],0,16-4);
+ cmd[0] = 1; //Empty incoming buffer
+ cmd[1] = 1; //Empty outgoing buffer
+ cmd[3] = 0; //Not a write to serial number
+ memset(&cmd[4],0,16-4);
- libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100);
+ libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100);
}
static void canusb_close(pcap_t* handle)
{
- loop = 0;
- pthread_join(canusb.worker, NULL);
-
- if (canusb.dev)
- {
- libusb_close(canusb.dev);
- canusb.dev = NULL;
- }
+ loop = 0;
+ pthread_join(canusb.worker, NULL);
+
+ if (canusb.dev)
+ {
+ libusb_close(canusb.dev);
+ canusb.dev = NULL;
+ }
}
static int canusb_activate(pcap_t* handle)
{
- handle->read_op = canusb_read_linux;
-
- handle->inject_op = canusb_inject_linux;
- handle->setfilter_op = canusb_setfilter_linux;
- handle->setdirection_op = canusb_setdirection_linux;
- handle->getnonblock_op = pcap_getnonblock_fd;
- handle->setnonblock_op = pcap_setnonblock_fd;
- handle->stats_op = canusb_stats_linux;
- handle->cleanup_op = canusb_close;
-
- /* Initialize some components of the pcap structure. */
- handle->bufsize = 32;
- handle->offset = 8;
- handle->linktype = DLT_CAN_SOCKETCAN;
- handle->set_datalink_op = NULL;
-
- char* serial = handle->opt.source + strlen("canusb");
-
- canusb.dev = canusb_opendevice(canusb.ctx,serial);
- if (!canusb.dev)
- {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device:");
- return PCAP_ERROR;
- }
-
- canusb_clearbufs(&canusb);
-
- handle->fd = canusb_startcapture(&canusb);
- handle->selectable_fd = handle->fd;
-
- return 0;
+ char *serial;
+
+ handle->read_op = canusb_read_linux;
+
+ handle->inject_op = canusb_inject_linux;
+ handle->setfilter_op = canusb_setfilter_linux;
+ handle->setdirection_op = canusb_setdirection_linux;
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->stats_op = canusb_stats_linux;
+ handle->cleanup_op = canusb_close;
+
+ /* Initialize some components of the pcap structure. */
+ handle->bufsize = 32;
+ handle->offset = 8;
+ handle->linktype = DLT_CAN_SOCKETCAN;
+ handle->set_datalink_op = NULL;
+
+ serial = handle->opt.source + strlen(CANUSB_IFACE);
+ canusb.serial = strdup(serial);
+
+ canusb.dev = canusb_opendevice(canusb.ctx,serial);
+ if (!canusb.dev)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device:");
+ return PCAP_ERROR;
+ }
+
+ canusb_clearbufs(&canusb);
+
+ handle->fd = canusb_startcapture(&canusb);
+ handle->selectable_fd = handle->fd;
+
+ return 0;
}
@@ -345,83 +382,85 @@ static int canusb_activate(pcap_t* handle)
static int
canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
- static struct timeval firstpacket = { -1, -1};
+ static struct timeval firstpacket = { -1, -1};
- int msgsent = 0;
- int i = 0;
- struct CAN_Msg msg;
- struct pcap_pkthdr pkth;
+ int msgsent = 0;
+ int i = 0;
+ struct CAN_Msg msg;
+ struct pcap_pkthdr pkth;
- while(i < max_packets)
- {
- usleep(10 * 1000);
- int n = read(handle->fd, &msg, sizeof(msg));
- if (n <= 0) break;
- pkth.caplen = pkth.len = n;
- pkth.caplen -= 4;
- pkth.caplen -= 8 - msg.length;
+ while(i < max_packets)
+ {
+ int n;
+ usleep(10 * 1000);
+ n = read(handle->fd, &msg, sizeof(msg));
+ if (n <= 0)
+ break;
+ pkth.caplen = pkth.len = n;
+ pkth.caplen -= 4;
+ pkth.caplen -= 8 - msg.length;
- if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1))
- gettimeofday(&firstpacket, NULL);
+ if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1))
+ gettimeofday(&firstpacket, NULL);
- pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000;
- pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100);
- if (pkth.ts.tv_usec > 1000000)
- {
- pkth.ts.tv_usec -= 1000000;
- pkth.ts.tv_sec++;
- }
+ pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000;
+ pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100);
+ if (pkth.ts.tv_usec > 1000000)
+ {
+ pkth.ts.tv_usec -= 1000000;
+ pkth.ts.tv_sec++;
+ }
- callback(user, &pkth, (void*)&msg.id);
- i++;
- }
+ callback(user, &pkth, (void*)&msg.id);
+ i++;
+ }
- return i;
+ return i;
}
static int
canusb_inject_linux(pcap_t *handle, const void *buf, size_t size)
{
- /* not yet implemented */
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on canusb devices");
- return (-1);
+ /* not yet implemented */
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on canusb devices");
+ return (-1);
}
static int
canusb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
{
- /* not yet implemented */
- stats->ps_recv = 0; /* number of packets received */
- stats->ps_drop = 0; /* number of packets dropped */
- stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */
- return 0;
+ /* not yet implemented */
+ stats->ps_recv = 0; /* number of packets received */
+ stats->ps_drop = 0; /* number of packets dropped */
+ stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */
+ return 0;
}
static int
canusb_setfilter_linux(pcap_t *p, struct bpf_program *fp)
{
- /* not yet implemented */
- return 0;
+ /* not yet implemented */
+ return 0;
}
static int
canusb_setdirection_linux(pcap_t *p, pcap_direction_t d)
{
- /* no support for PCAP_D_OUT */
- if (d == PCAP_D_OUT)
- {
- snprintf(p->errbuf, sizeof(p->errbuf),
- "Setting direction to PCAP_D_OUT is not supported on this interface");
- return -1;
- }
+ /* no support for PCAP_D_OUT */
+ if (d == PCAP_D_OUT)
+ {
+ snprintf(p->errbuf, sizeof(p->errbuf),
+ "Setting direction to PCAP_D_OUT is not supported on this interface");
+ return -1;
+ }
- p->direction = d;
+ p->direction = d;
- return 0;
+ return 0;
}