Created
June 1, 2016 23:23
-
-
Save pamaury/6cea172644423f6bc7b5faab163ab712 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <libusb.h> | |
#include <assert.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <time.h> | |
#include "usb_test_def.h" | |
libusb_context *ctx; | |
#define MIN(a,b) ((a)<(b)?(a):(b)); | |
uint64_t get_time_stamp() | |
{ | |
struct timeval tv; | |
gettimeofday(&tv,NULL); | |
return tv.tv_sec*(uint64_t)1000000+tv.tv_usec; | |
} | |
void main_loop(libusb_device_handle *handle) | |
{ | |
libusb_device *device=libusb_get_device(handle); | |
printf("device found at %d:%d\n", | |
libusb_get_bus_number(device), | |
libusb_get_device_address(device)); | |
struct libusb_device_descriptor dev_desc; | |
int res=libusb_get_device_descriptor(device,&dev_desc); | |
assert(res==0); | |
int config_id; | |
res=libusb_get_configuration(handle,&config_id); | |
assert(res==0); | |
struct libusb_config_descriptor *config; | |
res=libusb_get_active_config_descriptor(device,&config); | |
assert(res==0); | |
printf("configuration: %d\n",config_id); | |
printf("interfaces: %d\n",config->bNumInterfaces); | |
int test_interface=-1; | |
for(int i=0;i<config->bNumInterfaces;i++) | |
{ | |
printf("interface %d: alternative settings: %d\n",i,config->interface[i].num_altsetting); | |
for(int j=0;j<config->interface[i].num_altsetting;j++) | |
{ | |
printf("interface %d,%d: class=%#x\n",i,j,config->interface[i].altsetting[j].bInterfaceClass); | |
printf("interface %d,%d: subclass=%#x\n",i,j,config->interface[i].altsetting[j].bInterfaceSubClass); | |
if(config->interface[i].altsetting[j].bInterfaceClass==0xff && | |
config->interface[i].altsetting[j].bInterfaceSubClass==0xff && | |
config->interface[i].altsetting[j].bInterfaceProtocol==0) | |
test_interface=i; | |
} | |
} | |
printf("test interface: %d\n",test_interface); | |
const struct libusb_interface_descriptor *interface=&config->interface[test_interface].altsetting[0]; | |
res=libusb_claim_interface(handle,test_interface); | |
if(res!=0) | |
{ | |
printf("claim error: %d\n",res); | |
assert(false); | |
} | |
printf("endpoints: %d\n",interface->bNumEndpoints); | |
int bulk_in_ep=-1; | |
int bulk_out_ep=-1; | |
for(int i=0;i<interface->bNumEndpoints;i++) | |
{ | |
printf("endpoint %d: addr=%d dir=%d type=%d\n",i, | |
interface->endpoint[i].bEndpointAddress&0x7,interface->endpoint[i].bEndpointAddress>>7, | |
interface->endpoint[i].bmAttributes&0x3); | |
if((interface->endpoint[i].bEndpointAddress&LIBUSB_ENDPOINT_DIR_MASK)==LIBUSB_ENDPOINT_IN && | |
(interface->endpoint[i].bmAttributes&LIBUSB_TRANSFER_TYPE_MASK)==LIBUSB_TRANSFER_TYPE_BULK) | |
bulk_in_ep=interface->endpoint[i].bEndpointAddress; | |
else if((interface->endpoint[i].bEndpointAddress&LIBUSB_ENDPOINT_DIR_MASK)==LIBUSB_ENDPOINT_OUT && | |
(interface->endpoint[i].bmAttributes&LIBUSB_TRANSFER_TYPE_MASK)==LIBUSB_TRANSFER_TYPE_BULK) | |
bulk_out_ep=interface->endpoint[i].bEndpointAddress; | |
} | |
printf("bulk IN: %#02x\n", bulk_in_ep); | |
printf("bulk OUT: %#02x\n", bulk_out_ep); | |
printf("Starting write test...\n"); | |
#define BUF_SIZE 512 * 1024 | |
#define REPEAT_COUNT 100 | |
void *buffer = malloc(BUF_SIZE); | |
memset(buffer, 0, BUF_SIZE); | |
uint64_t start_time = get_time_stamp(); | |
bool failure = false; | |
for(int i = 0; i < REPEAT_COUNT; i++) | |
{ | |
int xfered; | |
int ret = libusb_bulk_transfer(handle, bulk_out_ep, buffer, BUF_SIZE, &xfered, 1000); | |
if(ret != 0) | |
{ | |
printf("usb error: %d\n", ret); | |
failure = true; | |
break; | |
} | |
if(xfered != BUF_SIZE) | |
{ | |
printf("short transfer: %d < %d\n", xfered, BUF_SIZE); | |
failure = true; | |
break; | |
} | |
printf("."); | |
} | |
if(!failure) | |
{ | |
uint64_t end_time = get_time_stamp(); | |
unsigned count = REPEAT_COUNT * BUF_SIZE; | |
unsigned time_diff = (end_time - start_time) / 1000; | |
printf("\n"); | |
printf("Wrote %u bytes in %u ms. Average speed is %u kB/s.\n", | |
count, time_diff, count / time_diff); | |
} | |
libusb_release_interface(handle,test_interface); | |
} | |
bool is_sansa(libusb_device *dev) | |
{ | |
struct libusb_device_descriptor dev_desc; | |
int res=libusb_get_device_descriptor(dev,&dev_desc); | |
assert(res==0); | |
return dev_desc.idVendor==0x0781 && dev_desc.idProduct==0x74e1; | |
} | |
int main(int argc,char **argv) | |
{ | |
(void)argc; | |
(void)argv; | |
assert(libusb_init(&ctx)==0); | |
libusb_set_debug(NULL,3); | |
libusb_device **device_list; | |
ssize_t list_size=libusb_get_device_list(NULL,&device_list); | |
assert(list_size>=0); | |
libusb_device *found = NULL; | |
for(ssize_t i=0;i<list_size;i++) | |
{ | |
if(is_sansa(device_list[i])) | |
found=device_list[i]; | |
} | |
if(found) | |
{ | |
libusb_device_handle *handle; | |
int err=libusb_open(found,&handle); | |
assert(err==0); | |
main_loop(handle); | |
libusb_close(handle); | |
} | |
else | |
printf("No device found\n"); | |
libusb_free_device_list(device_list,1); | |
libusb_exit(NULL); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment