Generic example for QNX
#include "stddef.h"
#include "stdlib.h"
#include "stdio.h"
#include "errno.h"
#include "sys/usbdi.h"
/* Structures */
typedef struct _buffer_data_bundle buffer_data;
struct _buffer_data_bundle{
int length;
void* ptr;
};
/* Global Variables */
struct usbd_connection* conn = NULL;
/* Function Declarations */
void on_usbd_insert(struct usbd_connection* conn, usbd_device_instance_t *inst);
void on_usbd_remove(struct usbd_connection* conn, usbd_device_instance_t *inst);
void urb_callback(struct usbd_urb* urb, struct usbd_pipe* pipe, void* user_data);
void signal_handler(int signo);
/**
* USBD Insert: Called for each device in the tree on connection, and on device insertion
* -> Attempt to attach to the matching device
* -> Set up an I/O Callback at its input endpoints
*/
void on_usbd_insert(struct usbd_connection* conn, usbd_device_instance_t *inst){
/* Attempt to attach to the device */
struct usbd_device* device = NULL;
int ret = usbd_attach(conn, inst, 0, &device);
if(ret != EOK) return;
/* Parse for endpoints */
usbd_endpoint_descriptor_t *desc;
struct usbd_desc_node *node;
for (int endpoint_index = 0; (desc = (usbd_endpoint_descriptor_t*) usbd_parse_descriptors(device, NULL, USB_DESC_ENDPOINT,
endpoint_index, &node)) != NULL; ++endpoint_index)
{
/* Read the required Endpoint Info */
/* Note this example is specifically for bulk transfer input endpoints */
if((desc->bEndpointAddress & 0b10000000) != 0b10000000) return; //Not an input endpoint, as LSB in endpoint is not 0b1
if((desc->bmAttributes & 0b11) != 0b10) return; //Not a bulk endpoint, as bits 0...1 are not 0b10
/* Attempt to allocate space */
void* buffer = usbd_alloc(desc->wMaxPacketSize);
if(buffer == NULL) continue; //Failed to Allocate
struct usbd_urb * urb = usbd_alloc_urb(NULL);
if(urb == NULL){
usbd_free(buffer);
continue;
}
/* Open up a pipe */
struct usbd_pipe *pipe;
if( usbd_open_pipe(device, desc, &pipe) != EOK){
usbd_free(buffer);
usbd_free_urb(urb);
continue;
}
/* Setup User Data for Transfer */
buffer_data* user_data = calloc(1, sizeof(buffer_data));
user_data->length = desc->wMaxPacketSize;
user_data->ptr = buffer;
/* Setup & Initiate Transfer */
usbd_setup_bulk(urb, URB_DIR_IN, buffer, desc->wMaxPacketSize);
usbd_io(urb, pipe, urb_callback, user_data, USBD_TIME_INFINITY);
}
}
/**
* USBD Remove: Called on device removal
* -> Checks if we have an attached device
* -> Removes attached device as needed
*/
void on_usbd_remove(struct usbd_connection* conn, usbd_device_instance_t *inst){
struct usbd_device * device;
device = usbd_device_lookup(conn, inst);
if(device != NULL){
usbd_detach(device);
}
}
/**
* URB Callback: Callback for handling URB receipt.
* *Assuming IN direction:
* -> Prints all data received in word format (AABBCCDD EEFF0011 22334455)
* -> Re-queues a URB for processing at the same pipe for the next input.
*/
void urb_callback(struct usbd_urb* urb, struct usbd_pipe* pipe, void* user_data){
/* Get a data pointer and length */
buffer_data * buf_data = (buffer_data *)(user_data);
uint8_t * buffer = (uint8_t *)(buf_data->ptr);
/* Print byte breakdown of received data */
/* Note: This groups bytes by word (assuming word=4 bytes) */
/* This is where any processing on the data would go (or you could pass it to another thread) */
#define WORD_LEN 4
printf("Receive:");
for(int byteno = 0; byteno < buf_data->length; byteno++){
printf("%02x", buffer[byteno]);
if(byteno % WORD_LEN == (WORD_LEN - 1))
printf(" ");
}
printf("\n");
/* Prepare for re-queueing (continuous reporting) */
usbd_setup_bulk(urb, URB_DIR_IN, ((buffer_data*)user_data)->ptr, buf_data->length);
/* re-submit for I/O */
usbd_io(urb, pipe, urb_callback, user_data, USBD_TIME_INFINITY);
}
/**
* Signal Handler: Quits program safely when terminated (frees memory)
*/
void signal_handler(int signo){
if(conn != NULL) usbd_disconnect(conn); //NOTE: this also detaches associated devices and closes pipes!
_exit(0);
}
/**
* Main Function: Called when ran.
* First, sets up the connection and insertion/removal callbacks
* Then, sets up signal handling so the program can stop when terminated (via ctrl+c)
* Finally, loops until signal is reached. (Alternatively: Waits for some condition to be met)
*/
int main(int argc, char* argv[]){
/* Initialize USBD connection */
usbd_device_ident_t filter = {
USBD_CONNECT_WILDCARD,
USBD_CONNECT_WILDCARD,
USBD_CONNECT_WILDCARD,
USBD_CONNECT_WILDCARD,
USBD_CONNECT_WILDCARD
};
usbd_funcs_t functions = {
_USBDI_NFUNCS,
on_usbd_insert,
on_usbd_remove,
NULL /* Indicate that we do not need to receive any other events */
};
usbd_connect_parm_t connect_parms = {
NULL, /* Indicate that the default io-usb path is correct */
USB_VERSION,
USBD_VERSION,
0, /* No flags to be passed */
argc,
argv,
0, /* Default event buffer size */
&filter,
&functions
};
/* Attempt to start a connection via usbd_connect*/
int error;
struct usbd_connection *connection; /* Used to store a reference to the connection */
error = usbd_connect(&connect_parms, &connection);
if(error!=EOK) _exit(1);
/* Signals */
signal (SIGHUP, SIG_IGN);
signal (SIGPWR, SIG_IGN);
signal (SIGTERM, signal_handler);
signal (SIGKILL, signal_handler);
/* Loop until SIGTERM/SIGKILL */
for( ; ; ) sleep(60);
}
Page updated: