1238603Sjoerg/* ---------------------------------------------------------------------------- 2238603Sjoerg * "THE BEER-WARE LICENSE" (Revision 42) (by Poul-Henning Kamp): 3238603Sjoerg * <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you 4238603Sjoerg * can do whatever you want with this stuff. If we meet some day, and you think 5238603Sjoerg * this stuff is worth it, you can buy me a beer in return. Joerg Wunsch 6238603Sjoerg * ---------------------------------------------------------------------------- 7238603Sjoerg * 8238603Sjoerg * $FreeBSD$ 9238603Sjoerg */ 10238603Sjoerg 11238603Sjoerg/* 12238603Sjoerg * Simple demo program to illustrate the handling of FreeBSD's 13238603Sjoerg * libusb20. 14238603Sjoerg * 15238603Sjoerg * Issues a bulk output, and then requests a bulk input. 16238603Sjoerg */ 17238603Sjoerg 18238603Sjoerg/* 19238603Sjoerg * Examples: 20238603Sjoerg * Just list all VID:PID pairs 21238603Sjoerg * ./bulk 22238603Sjoerg * 23238603Sjoerg * Say "hello" to an Atmel JTAGICEmkII. 24238603Sjoerg * ./bulk -o 2 -i 0x82 -v 0x03eb -p 0x2103 0x1b 0 0 1 0 0 0 0x0e 1 0xf3 0x97 25238603Sjoerg * 26238603Sjoerg * Return the INQUIRY data of an USB mass storage device. 27238603Sjoerg * (It's best to have the umass(4) driver unloaded while doing such 28238603Sjoerg * experiments, and perform a "usbconfig reset" for the device if it 29238603Sjoerg * gets stuck.) 30238603Sjoerg * ./bulk -v 0x5e3 -p 0x723 -i 0x81 -o 2 0x55 0x53 0x42 0x43 1 2 3 4 31 12 0x80 0x24 0 0 0 0x12 0 0 0 36 0 0 0 0 0 0 0 0 0 0 31238603Sjoerg */ 32238603Sjoerg 33238603Sjoerg 34238603Sjoerg#include <limits.h> 35238603Sjoerg#include <stdio.h> 36238603Sjoerg#include <stdint.h> 37238603Sjoerg#include <stdlib.h> 38238603Sjoerg#include <sysexits.h> 39238603Sjoerg#include <unistd.h> 40238603Sjoerg 41238603Sjoerg#include <libusb20.h> 42238603Sjoerg#include <libusb20_desc.h> 43238603Sjoerg 44269879Semaste#include "util.h" 45238603Sjoerg 46238603Sjoerg/* 47238603Sjoerg * If you want to see the details of the internal datastructures 48238603Sjoerg * in the debugger, unifdef the following. 49238603Sjoerg */ 50238603Sjoerg#ifdef DEBUG 51238603Sjoerg# include <sys/queue.h> 52238603Sjoerg# include "/usr/src/lib/libusb/libusb20_int.h" 53238603Sjoerg#endif 54238603Sjoerg 55238603Sjoerg#define BUFLEN 64 56238603Sjoerg 57238603Sjoerg#define TIMEOUT 5000 /* 5 s */ 58238603Sjoerg 59238603Sjoergint in_ep, out_ep; /* endpoints */ 60238603Sjoerguint8_t out_buf[BUFLEN]; 61238603Sjoerguint16_t out_len; 62238603Sjoerg 63238603Sjoergstatic void 64238603Sjoergdoit(struct libusb20_device *dev) 65238603Sjoerg{ 66238603Sjoerg int rv; 67238603Sjoerg 68238603Sjoerg /* 69238603Sjoerg * Open the device, allocating memory for two possible (bulk or 70238603Sjoerg * interrupt) transfers. 71238603Sjoerg * 72238603Sjoerg * If only control transfers are intended (via 73238603Sjoerg * libusb20_dev_request_sync()), transfer_max can be given as 0. 74238603Sjoerg */ 75238603Sjoerg if ((rv = libusb20_dev_open(dev, 2)) != 0) 76238603Sjoerg { 77269879Semaste fprintf(stderr, "libusb20_dev_open: %s\n", libusb20_strerror(rv)); 78238603Sjoerg return; 79238603Sjoerg } 80238603Sjoerg 81238603Sjoerg /* 82238603Sjoerg * If the device has more than one configuration, select the desired 83238603Sjoerg * one here. 84238603Sjoerg */ 85238603Sjoerg if ((rv = libusb20_dev_set_config_index(dev, 0)) != 0) 86238603Sjoerg { 87269879Semaste fprintf(stderr, "libusb20_dev_set_config_index: %s\n", libusb20_strerror(rv)); 88238603Sjoerg return; 89238603Sjoerg } 90238603Sjoerg 91238603Sjoerg /* 92238603Sjoerg * Two transfers have been requested in libusb20_dev_open() above; 93238603Sjoerg * obtain the corresponding transfer struct pointers. 94238603Sjoerg */ 95238603Sjoerg struct libusb20_transfer *xfr_out = libusb20_tr_get_pointer(dev, 0); 96238603Sjoerg struct libusb20_transfer *xfr_in = libusb20_tr_get_pointer(dev, 1); 97238603Sjoerg 98238603Sjoerg if (xfr_in == NULL || xfr_out == NULL) 99238603Sjoerg { 100269879Semaste fprintf(stderr, "libusb20_tr_get_pointer: %s\n", libusb20_strerror(rv)); 101238603Sjoerg return; 102238603Sjoerg } 103238603Sjoerg 104238603Sjoerg /* 105238603Sjoerg * Open both transfers, the "out" one for the write endpoint, the 106238603Sjoerg * "in" one for the read endpoint (ep | 0x80). 107238603Sjoerg */ 108238603Sjoerg if ((rv = libusb20_tr_open(xfr_out, 0, 1, out_ep)) != 0) 109238603Sjoerg { 110269879Semaste fprintf(stderr, "libusb20_tr_open: %s\n", libusb20_strerror(rv)); 111238603Sjoerg return; 112238603Sjoerg } 113238603Sjoerg if ((rv = libusb20_tr_open(xfr_in, 0, 1, in_ep)) != 0) 114238603Sjoerg { 115269879Semaste fprintf(stderr, "libusb20_tr_open: %s\n", libusb20_strerror(rv)); 116238603Sjoerg return; 117238603Sjoerg } 118238603Sjoerg 119238603Sjoerg uint8_t in_buf[BUFLEN]; 120238603Sjoerg uint32_t rlen; 121238603Sjoerg 122238603Sjoerg if (out_len > 0) 123238603Sjoerg { 124238603Sjoerg if ((rv = libusb20_tr_bulk_intr_sync(xfr_out, out_buf, out_len, &rlen, TIMEOUT)) 125238603Sjoerg != 0) 126238603Sjoerg { 127269879Semaste fprintf(stderr, "libusb20_tr_bulk_intr_sync (OUT): %s\n", libusb20_strerror(rv)); 128238603Sjoerg } 129238603Sjoerg printf("sent %d bytes\n", rlen); 130238603Sjoerg } 131238603Sjoerg 132238603Sjoerg if ((rv = libusb20_tr_bulk_intr_sync(xfr_in, in_buf, BUFLEN, &rlen, TIMEOUT)) 133238603Sjoerg != 0) 134238603Sjoerg { 135269879Semaste fprintf(stderr, "libusb20_tr_bulk_intr_sync: %s\n", libusb20_strerror(rv)); 136238603Sjoerg } 137238603Sjoerg printf("received %d bytes\n", rlen); 138238603Sjoerg if (rlen > 0) 139238603Sjoerg print_formatted(in_buf, rlen); 140238603Sjoerg 141238603Sjoerg libusb20_tr_close(xfr_out); 142238603Sjoerg libusb20_tr_close(xfr_in); 143238603Sjoerg 144238603Sjoerg libusb20_dev_close(dev); 145238603Sjoerg} 146238603Sjoerg 147238603Sjoergstatic void 148238603Sjoergusage(void) 149238603Sjoerg{ 150238603Sjoerg fprintf(stderr, 151238603Sjoerg "Usage ./usb -i <IN_EP> -o <OUT_EP> -v <VID> -p <PID> [<outdata> ...\n]"); 152238603Sjoerg exit(EX_USAGE); 153238603Sjoerg} 154238603Sjoerg 155238603Sjoergint 156238603Sjoergmain(int argc, char **argv) 157238603Sjoerg{ 158238603Sjoerg unsigned int vid = UINT_MAX, pid = UINT_MAX; /* impossible VID:PID */ 159238603Sjoerg int c; 160238603Sjoerg 161238603Sjoerg while ((c = getopt(argc, argv, "i:o:p:v:")) != -1) 162238603Sjoerg switch (c) 163238603Sjoerg { 164238603Sjoerg case 'i': 165238603Sjoerg in_ep = strtol(optarg, NULL, 0); 166238603Sjoerg break; 167238603Sjoerg 168238603Sjoerg case 'o': 169238603Sjoerg out_ep = strtol(optarg, NULL, 0); 170238603Sjoerg break; 171238603Sjoerg 172238603Sjoerg case 'p': 173238603Sjoerg pid = strtol(optarg, NULL, 0); 174238603Sjoerg break; 175238603Sjoerg 176238603Sjoerg case 'v': 177238603Sjoerg vid = strtol(optarg, NULL, 0); 178238603Sjoerg break; 179238603Sjoerg 180238603Sjoerg default: 181238603Sjoerg usage(); 182238603Sjoerg break; 183238603Sjoerg } 184238603Sjoerg argc -= optind; 185238603Sjoerg argv += optind; 186238603Sjoerg 187238603Sjoerg if (vid != UINT_MAX || pid != UINT_MAX) 188238603Sjoerg { 189238603Sjoerg if (in_ep == 0 || out_ep == 0) 190238603Sjoerg { 191238603Sjoerg usage(); 192238603Sjoerg } 193238603Sjoerg if ((in_ep & 0x80) == 0) 194238603Sjoerg { 195238603Sjoerg fprintf(stderr, "IN_EP must have bit 7 set\n"); 196238603Sjoerg return (EX_USAGE); 197238603Sjoerg } 198238603Sjoerg 199238603Sjoerg if (argc > 0) 200238603Sjoerg { 201238603Sjoerg for (out_len = 0; argc > 0 && out_len < BUFLEN; out_len++, argc--) 202238603Sjoerg { 203238603Sjoerg unsigned n = strtoul(argv[out_len], 0, 0); 204238603Sjoerg if (n > 255) 205238603Sjoerg fprintf(stderr, 206238603Sjoerg "Warning: data #%d 0x%0x > 0xff, truncating\n", 207238603Sjoerg out_len, n); 208238603Sjoerg out_buf[out_len] = (uint8_t)n; 209238603Sjoerg } 210238603Sjoerg out_len++; 211238603Sjoerg if (argc > 0) 212238603Sjoerg fprintf(stderr, 213238603Sjoerg "Data count exceeds maximum of %d, ignoring %d elements\n", 214238603Sjoerg BUFLEN, optind); 215238603Sjoerg } 216238603Sjoerg } 217238603Sjoerg 218238603Sjoerg struct libusb20_backend *be; 219238603Sjoerg struct libusb20_device *dev; 220238603Sjoerg 221238603Sjoerg if ((be = libusb20_be_alloc_default()) == NULL) 222238603Sjoerg { 223238603Sjoerg perror("libusb20_be_alloc()"); 224238603Sjoerg return 1; 225238603Sjoerg } 226238603Sjoerg 227238603Sjoerg dev = NULL; 228238603Sjoerg while ((dev = libusb20_be_device_foreach(be, dev)) != NULL) 229238603Sjoerg { 230238603Sjoerg struct LIBUSB20_DEVICE_DESC_DECODED *ddp = 231238603Sjoerg libusb20_dev_get_device_desc(dev); 232238603Sjoerg 233238603Sjoerg printf("Found device %s (VID:PID = 0x%04x:0x%04x)\n", 234238603Sjoerg libusb20_dev_get_desc(dev), 235238603Sjoerg ddp->idVendor, ddp->idProduct); 236238603Sjoerg 237238603Sjoerg if (ddp->idVendor == vid && ddp->idProduct == pid) 238238603Sjoerg doit(dev); 239238603Sjoerg } 240238603Sjoerg 241238603Sjoerg libusb20_be_free(be); 242238603Sjoerg return 0; 243238603Sjoerg} 244