Esempio n. 1
1
int main()
{
	int r; // return values

	r = libusb_init(NULL);
	if (r < 0) error("ERROR: failed to initialize libusb (r = %d)\n", r);

	libusb_set_debug(NULL, 3);

	libusb_device **list;
	ssize_t cnt = libusb_get_device_list(NULL, &list);
	if (cnt < 0) error("ERROR: failed to get device list (cnt = %d)\n", cnt);


	for (ssize_t i = 0; i < cnt; i++) {
		libusb_device *dev = list[i];
		struct libusb_device_descriptor desc;
		int r = libusb_get_device_descriptor(dev, &desc);
		if (r < 0) error("ERROR: failed to get device descriptor (r = %d)\n", r);

		if (desc.idVendor == pololuVendorID) {

			for (int j = 0; j < NUM_PRODUCT_IDS && smc_count < 2; j++) {

				if (desc.idProduct == smcProductIDs[j]) {
					libusb_device_handle *handle;
					r = libusb_open(dev, &handle);
					if (r < 0) error("ERROR: failed to open device (r = %d)\n", r);

					smc_list[smc_count] = handle;
					smc_count++;

					char buf[100];
					r = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buf, sizeof(buf));
					if (r < 0) error("ERROR: failed to get serial number string from device (r = %d)\n", r);

					switch(desc.idProduct) {
						case 0x98: printf("18v15"); break;
						case 0x9A: printf("24v12"); break;
						case 0x9C: printf("18v25"); break;
						case 0x9E: printf("24v23"); break;
						case 0xA1: printf("18v7"); break;
					}
					printf(" #%s\n", buf);

					break;
				}
			}
		}
	}

	if (smc_count == 1)
		printf("1 Simple Motor Controller found.\n", smc_count);
	else
		printf("%d Simple Motor Controllers found.\n", smc_count);
		
	printf("Sending ExitSafeStart...\n");
	for (int i = 0; i < smc_count; i++) {
		r = libusb_control_transfer(smc_list[i], 0x40, ExitSafeStart, 0, 0, NULL, 0, 5000);
		if (r < 0) error("ERROR: failed to exit safe start (r = %d)\n", r);
	}

	set_speeds(3200, 3200);
	sleep(4);
	set_speeds(0, 0);

	/*char c;

	while (1)
	{
		scanf("%c", &c);
		fflush(stdin);

		printf("input: %c\n", c);

		switch (c) {
			case 'w':
				set_speeds(3200, 3200);
				break;
			case 'a':
				set_speeds(-3200, 3200);
				break;	
			case 's':
				set_speeds(-3200, -3200);
				break;	
			case 'd':
				set_speeds(3200, -3200);
				break;	
			default:
				set_speeds(0, 0);
		}
		usleep(500000);
	}*/

	for (int i = 0; i < smc_count; i++)
		libusb_close(smc_list[i]);

	libusb_free_device_list(list, 1);
	libusb_exit(NULL);

	return 0;
}
Esempio n. 2
0
int AndrOA::connect_to_accessory(void)
{
    /*
     *Each usb device is manipulated with a libusb_device
     and libusb_device_handle objects in libusb. The libusb API
     ties an open device to a specific interface.
     This means that if you want to claim multiple interfaces
     on a device, you should open the device multiple times to
     receive one libusb_dev_handle for each interface you want
     to communicate with. Don't forget to call usb_claim_interface.
     */
    int returned = libusb_init(&context);
    if(returned != 0){
        printf("ERROR libusb_init failed\n");
        return 1;
    }

    unsigned char ioBuffer[2];
    int protocol;
    int res;
    int tries = 10;
    uint16_t idVendor, idProduct;

    /* Search for connected devices */
    protocol = search_for_device(context, &idVendor, &idProduct);

    if ( protocol < 0 )
    {
        printf("ERROR Android accessory device not found.\n");
        return -1;
    } else if( protocol == 0 )
    { // Check if we are already in accessory mode
        device_handle = libusb_open_device_with_vid_pid(context,
                idVendor, idProduct);
        libusb_claim_interface(device_handle, 0);
        return 0;
    }

    versionProtocol = protocol;
    device_handle = libusb_open_device_with_vid_pid(context,
            idVendor, idProduct);
    libusb_claim_interface(device_handle, 0);
    usleep(800);

    /* Send the accessory info */
    send_string(AOA_STRING_MANUFACTURER, (char*)manufacturer);
    send_string(AOA_STRING_MODEL, (char*)model);
    send_string(AOA_STRING_DESCRIPTION, (char*)description);
    send_string(AOA_STRING_VERSION, (char*)version);
    send_string(AOA_STRING_URI, (char*)url);
    send_string(AOA_STRING_SERIAL, (char*)serial);

    /* Swich to accessory mode */
    res = libusb_control_transfer(device_handle, 0x40,
            AOA_START, 0, 0, NULL, 0, 0);
    if(res < 0){
        libusb_close(device_handle);
        device_handle = NULL;
        return -2;
    }

    /* Check that the devicehandle is reall NULLED */
    if(device_handle != NULL){
        libusb_close(device_handle);
        device_handle = NULL;
    }

    usleep(8000);

    printf("connecting to a new ProductID...\n");
    //attempt to connect to new PID,
    //if that doesn't work try AOA_PID_ALT
    for(;;){
        --tries;
        int tmpRes = search_for_device(context, &idVendor, &idProduct);
        if(tmpRes != 0){
            continue;
        }
        device_handle = libusb_open_device_with_vid_pid(context, idVendor,
                idProduct);
        if( device_handle == NULL ){
            if( tries < 0 ){
                return -1;
            }
        } else{
            break;
        }
        sleep(1);
    }

    res = libusb_claim_interface(device_handle, 0);
    if(res < 0){
        return -3;
    }

    printf("Established Android accessory connection.\n");
    return 0;
}
Esempio n. 3
0
int main(int argc, char **argv)
{
	int rc;
	libusb_device_handle *handle = NULL;
	rc = libusb_init(NULL);
	assert(rc == 0);

	if (argc <= 1) {
		printf("Usage: %s command arguments... [command...]\n"
			"	hex[dump] address length	Dumps memory region in hex\n"
			"	dump address length		Binary memory dump\n"
			"	exe[cute] address		Call function address\n"
			"	write address file		Store file contents into memory\n"
			"	ver[sion]			Show BROM version\n"
			"	clear address length		Clear memory\n"
			"	fill address length value	Fill memory\n"
			, argv[0]
		);
	}

	handle = libusb_open_device_with_vid_pid(NULL, 0x1f3a, 0xefe8);
	if (!handle) {
		fprintf(stderr, "A10 USB FEL device not found!");
		exit(1);
	}
	rc = libusb_claim_interface(handle, 0);
	assert(rc == 0);

	while (argc > 1 ) {
		int skip = 1;
		if (strncmp(argv[1], "hex", 3) == 0 && argc > 3) {
			aw_fel_hexdump(handle, strtoul(argv[2], NULL, 0), strtoul(argv[3], NULL, 0));
			skip = 3;
		} else if (strncmp(argv[1], "dump", 4) == 0 && argc > 3) {
			aw_fel_dump(handle, strtoul(argv[2], NULL, 0), strtoul(argv[3], NULL, 0));
			skip = 3;
		} else if ((strncmp(argv[1], "exe", 3) == 0 && argc > 2)
			) {
			aw_fel_execute(handle, strtoul(argv[2], NULL, 0));
			skip=3;
		} else if (strncmp(argv[1], "ver", 3) == 0 && argc > 1) {
			aw_fel_get_version(handle);
			skip=1;
		} else if (strcmp(argv[1], "write") == 0 && argc > 3) {
			size_t size;
			void *buf = load_file(argv[3], &size);
			aw_fel_write(handle, buf, strtoul(argv[2], NULL, 0), size);
			free(buf);
			skip=3;
		} else if (strcmp(argv[1], "clear") == 0 && argc > 2) {
			aw_fel_fill(handle, strtoul(argv[2], NULL, 0), strtoul(argv[3], NULL, 0), 0);
			skip=3;
		} else if (strcmp(argv[1], "fill") == 0 && argc > 3) {
			aw_fel_fill(handle, strtoul(argv[2], NULL, 0), strtoul(argv[3], NULL, 0), (unsigned char)strtoul(argv[4], NULL, 0));
			skip=4;
		} else {
			fprintf(stderr,"Invalid command %s\n", argv[1]);
			exit(1);
		}
		argc-=skip;
		argv+=skip;
	}

	return 0;
}
Esempio n. 4
0
static int lusb_open(void **driver,
                     struct bladerf_devinfo *info_in,
                     struct bladerf_devinfo *info_out)
{
    int status, i, n;
    int fx3_status;
    ssize_t count;
    struct bladerf_lusb *lusb = NULL;
    libusb_device **list = NULL;
    struct bladerf_devinfo thisinfo;

    libusb_context *context;

    /* Initialize libusb for device tree walking */
    status = libusb_init(&context);
    if (status) {
        log_error("Could not initialize libusb: %s\n",
                  libusb_error_name(status));
        status = error_conv(status);
        goto error;
    }

    /* We can only print this out when log output is enabled, or else we'll
     * get snagged by -Werror=unused-but-set-variable */
#   ifdef LOGGING_ENABLED
    {
        char buf[64];
        get_libusb_version(buf, sizeof(buf));
        log_verbose("Using libusb version: %s\n", buf);
    }
#   endif

    /* Iterate through all the USB devices */
    count = libusb_get_device_list(context, &list);
    for (i = 0, n = 0; i < count; i++) {
        if (device_is_bladerf(list[i])) {
            log_verbose("Found a bladeRF (based upon VID/PID)\n");

            /* Open the USB device and get some information */
            status = get_devinfo(list[i], &thisinfo);
            if(status < 0) {
                log_debug("Could not open bladeRF device: %s\n",
                          libusb_error_name(status) );
                status = 0;
                continue; /* Continue trying the next devices */
            }
            thisinfo.instance = n++;

            /* Check to see if this matches the info struct */
            if (bladerf_devinfo_matches(&thisinfo, info_in)) {

                lusb = (struct bladerf_lusb *)malloc(sizeof(struct bladerf_lusb));
                if (lusb == NULL) {
                    log_debug("Skipping instance %d due to failed allocation\n",
                              thisinfo.instance);
                    lusb = NULL;
                    continue;   /* Try the next device */
                }

                lusb->context = context;
                lusb->dev = list[i];

                status = libusb_open(list[i], &lusb->handle);
                if (status < 0) {
                    log_debug("Skipping - could not open device: %s\n",
                               libusb_error_name(status));

                    /* Keep trying other devices */
                    status = 0;
                    free(lusb);
                    lusb = NULL;
                    continue;
                }

                status = libusb_claim_interface(lusb->handle, 0);
                if(status < 0) {
                    log_debug("Skipping - could not claim interface: %s\n",
                              libusb_error_name(status));

                    /* Keep trying other devices */
                    status = 0;
                    libusb_close(lusb->handle);
                    free(lusb);
                    lusb = NULL;
                    continue;
                }

                memcpy(info_out, &thisinfo, sizeof(struct bladerf_devinfo));
                *driver = lusb;
                break;

            } else {
                log_verbose("Devinfo doesn't match - skipping"
                            "(instance=%d, serial=%d, bus/addr=%d\n",
                            bladerf_instance_matches(&thisinfo, info_in),
                            bladerf_serial_matches(&thisinfo, info_in),
                            bladerf_bus_addr_matches(&thisinfo, info_in));
            }
        }

        if (device_is_fx3_bootloader(list[i])) {
            fx3_status = get_devinfo(list[i], &thisinfo);
            if (fx3_status != 0) {
                log_debug("Could not open FX3 bootloader device: %s\n",
                          libusb_error_name(fx3_status));
                continue;
            }

            log_info("Found FX3 bootloader device on bus=%d addr=%d. "
                     "This may be a bladeRF.\n",
                     thisinfo.usb_bus, thisinfo.usb_addr);

            log_info("Use bladeRF-cli command \"recover %d %d "
                     "<FX3 firmware>\" to boot the bladeRF firmware.\n",
                     thisinfo.usb_bus, thisinfo.usb_addr);
        }
    }


error:
    if (list) {
        libusb_free_device_list(list, 1);
    }

    if (lusb == NULL) {
        log_debug("No devices available on the libusb backend.\n");
        status = BLADERF_ERR_NODEV;
    }

    if (status != 0) {
        if (lusb != NULL) {
            if (lusb->handle) {
                libusb_close(lusb->handle);
            }

            free(lusb);
        }

        libusb_exit(context);
    }
    return status;
}
Esempio n. 5
0
int main(int argc, char **argv)
{
    const char *lua_init = "init.lua";
    std::vector< std::pair< exec_type, std::string > > startup_cmds;
    // parse command line
    while(1)
    {
        static struct option long_options[] =
        {
            {"help", no_argument, 0, '?'},
            {"quiet", no_argument, 0, 'q'},
            {0, 0, 0, 0}
        };

        int c = getopt_long(argc, argv, "?qi:e:f:", long_options, NULL);
        if(c == -1)
            break;
        switch(c)
        {
            case -1:
                break;
            case 'q':
                g_quiet = true;
                break;
            case '?':
                usage();
                break;
            case 'i':
                lua_init = optarg;
                break;
            case 'e':
                startup_cmds.push_back(std::make_pair(exec_cmd, std::string(optarg)));
                break;
            case 'f':
                startup_cmds.push_back(std::make_pair(exec_file, std::string(optarg)));
                break;
            default:
                abort();
        }
    }

    // load register descriptions
    std::vector< soc_t > socs;
    for(int i = optind; i < argc; i++)
    {
        socs.push_back(soc_t());
        if(!soc_desc_parse_xml(argv[i], socs[socs.size() - 1]))
        {
            printf("Cannot load description '%s'\n", argv[i]);
            return 2;
        }
    }

    // create usb context
    libusb_context *ctx;
    libusb_init(&ctx);
    libusb_set_debug(ctx, 3);

    // look for device
    if(!g_quiet)
        printf("Looking for hwstub device ...\n");
    // open first device
    libusb_device **list;
    ssize_t cnt = hwstub_get_device_list(ctx, &list);
    if(cnt <= 0)
    {
        printf("No device found\n");
        return 1;
    }
    libusb_device_handle *handle;
    if(libusb_open(list[0], &handle) != 0)
    {
        printf("Cannot open device\n");
        return 1;
    }
    libusb_free_device_list(list, 1);

    // admin stuff
    libusb_device *mydev = libusb_get_device(handle);
    if(!g_quiet)
    {
        printf("device found at %d:%d\n",
            libusb_get_bus_number(mydev),
            libusb_get_device_address(mydev));
    }
    g_hwdev = hwstub_open(handle);
    if(g_hwdev == NULL)
    {
        printf("Cannot open device!\n");
        return 1;
    }

    // get hwstub information
    int ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_VERSION, &g_hwdev_ver, sizeof(g_hwdev_ver));
    if(ret != sizeof(g_hwdev_ver))
    {
        printf("Cannot get version!\n");
        goto Lerr;
    }
    if(g_hwdev_ver.bMajor != HWSTUB_VERSION_MAJOR || g_hwdev_ver.bMinor < HWSTUB_VERSION_MINOR)
    {
        printf("Warning: this tool is possibly incompatible with your device:\n");
        printf("Device version: %d.%d.%d\n", g_hwdev_ver.bMajor, g_hwdev_ver.bMinor, g_hwdev_ver.bRevision);
        printf("Host version: %d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR);
    }

    // get memory layout information
    ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_LAYOUT, &g_hwdev_layout, sizeof(g_hwdev_layout));
    if(ret != sizeof(g_hwdev_layout))
    {
        printf("Cannot get layout: %d\n", ret);
        goto Lerr;
    }

    // get target
    ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_TARGET, &g_hwdev_target, sizeof(g_hwdev_target));
    if(ret != sizeof(g_hwdev_target))
    {
        printf("Cannot get target: %d\n", ret);
        goto Lerr;
    }

    // get STMP specific information
    if(g_hwdev_target.dID == HWSTUB_TARGET_STMP)
    {
        ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_STMP, &g_hwdev_stmp, sizeof(g_hwdev_stmp));
        if(ret != sizeof(g_hwdev_stmp))
        {
            printf("Cannot get stmp: %d\n", ret);
            goto Lerr;
        }
    }

    // get PP specific information
    if(g_hwdev_target.dID == HWSTUB_TARGET_PP)
    {
        ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_PP, &g_hwdev_pp, sizeof(g_hwdev_pp));
        if(ret != sizeof(g_hwdev_pp))
        {
            printf("Cannot get pp: %d\n", ret);
            goto Lerr;
        }
    }
    /** Init lua */

    // create lua state
    g_lua = luaL_newstate();
    if(g_lua == NULL)
    {
        printf("Cannot create lua state\n");
        return 1;
    }
    // import hwstub
    if(!my_lua_import_hwstub())
        printf("Cannot import hwstub description into Lua context\n");
    // open all standard libraires
    luaL_openlibs(g_lua);
    // import socs
    if(!my_lua_import_soc(socs))
        printf("Cannot import SoC descriptions into Lua context\n");

    if(luaL_dofile(g_lua, lua_init))
        printf("error in init: %s\n", lua_tostring(g_lua, -1));
    lua_pop(g_lua, lua_gettop(g_lua));

    /** start interactive mode */
    if(!g_quiet)
        printf("Starting interactive lua session. Type 'help()' to get some help\n");

    /** run startup commands */
    for(size_t i = 0; i < startup_cmds.size(); i++)
    {
        bool ret = false;
        if(!g_quiet)
            printf("Running '%s'...\n", startup_cmds[i].second.c_str());
        if(startup_cmds[i].first == exec_file)
            ret = luaL_dofile(g_lua, startup_cmds[i].second.c_str());
        else if(startup_cmds[i].first == exec_cmd)
            ret = luaL_dostring(g_lua, startup_cmds[i].second.c_str());
        if(ret)
            printf("error: %s\n", lua_tostring(g_lua, -1));
    }

    // use readline to provide some history and completion
    rl_bind_key('\t', rl_complete);
    while(!g_exit)
    {
        char *input = readline("> ");
        if(!input)
            break;
        add_history(input);
        // evaluate string
        if(luaL_dostring(g_lua, input))
            printf("error: %s\n", lua_tostring(g_lua, -1));
        // pop everything to start from a clean stack
        lua_pop(g_lua, lua_gettop(g_lua));
        free(input);
    }

    Lerr:
    // display log if handled
    if(!g_quiet)
        printf("Device log:\n");
    print_log(g_hwdev);
    hwstub_release(g_hwdev);
    return 1;
}
Esempio n. 6
0
static void *libusb_hid_init(void)
{
   unsigned i, count;
   int ret;
   struct libusb_device **devices;
   libusb_hid_t *hid = (libusb_hid_t*)calloc(1, sizeof(*hid));

   if (!hid)
      goto error;

   ret = libusb_init(&hid->ctx);

   if (ret < 0)
      goto error;

   if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
      goto error;

   hid->slots = pad_connection_init(MAX_USERS);

   if (!hid->slots)
      goto error;

   count = libusb_get_device_list(hid->ctx, &devices);

   for (i = 0; i < count; i++)
   {
      struct libusb_device_descriptor desc;
      libusb_get_device_descriptor(devices[i], &desc);

      if (desc.idVendor > 0 && desc.idProduct > 0)
         add_adapter(hid, devices[i]);
   }

   if (count > 0)
      libusb_free_device_list(devices, 1);

   ret = libusb_hotplug_register_callback(
         hid->ctx,
         (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
         LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
         (libusb_hotplug_flag)LIBUSB_HOTPLUG_ENUMERATE,
         LIBUSB_HOTPLUG_MATCH_ANY,
         LIBUSB_HOTPLUG_MATCH_ANY,
         LIBUSB_HOTPLUG_MATCH_ANY,
         libusb_hid_hotplug_callback,
         hid,
         &hid->hp);

   if (ret != LIBUSB_SUCCESS)
   {
      RARCH_ERR("Error creating a hotplug callback.\n");
      goto error;
   }

   hid->poll_thread = sthread_create(poll_thread, hid);

   if (!hid->poll_thread)
   {
      RARCH_ERR("Error creating polling thread");
      goto error;
   }

   return hid;

error:
   libusb_hid_free(hid);
   return NULL;
}
Esempio n. 7
0
int main(int argc, char **argv)
{
	char *gsmtap_host = "127.0.0.1";
	int rc;
	int c, ret = 1;
	int skip_atr = 0;
	int keep_running = 0;
	int dump_usb = 0;
	int replay = 0;
	struct libusb_device_handle *devh;

	print_welcome();

	while (1) {
		int option_index = 0;

		c = getopt_long(argc, argv, "i:ahkd:r:", opts, &option_index);
		if (c == -1)
			break;
		switch (c) {
		case 'h':
			print_help();
			exit(0);
			break;
		case 'i':
			gsmtap_host = optarg;
			break;
		case 'a':
			skip_atr = 1;
			break;
		case 'k':
			keep_running = 1;
			break;
		case 'd':
			dump_usb = 1;
			dump_usb_file = fopen(optarg,"wb");
			break;
		case 'r':
			replay = 1;
			dump_usb_file =  fopen(optarg,"rb");
			printf("replaying file %s...\n",optarg);
			break;
		}
	}

	rc = libusb_init(NULL);
	if (rc < 0) {
		fprintf(stderr, "libusb initialization failed\n");
		goto close_exit;
	}

	g_gti = gsmtap_source_init(gsmtap_host, GSMTAP_UDP_PORT, 0);
	if (!g_gti) {
		perror("unable to open GSMTAP");
		goto close_exit;
	}
	gsmtap_source_add_sink(g_gti);

	as = apdu_split_init(&apdu_out_cb, NULL);
	if (!as)
		goto release_exit;

	if (replay) {
		printf("done replaying file...\n");
		replay_mainloop(dump_usb_file);
		fclose(dump_usb_file);
	}
	else
	{
		do {
			devh = libusb_open_device_with_vid_pid(NULL, SIMTRACE_USB_VENDOR, SIMTRACE_USB_PRODUCT);
			if (!devh) {
				fprintf(stderr, "can't open USB device\n");
				goto close_exit;
			}

			rc = libusb_claim_interface(devh, 0);
			if (rc < 0) {
				fprintf(stderr, "can't claim interface; rc=%d\n", rc);
				goto close_exit;
			}

			run_mainloop(devh);
			ret = 0;

			libusb_release_interface(devh, 0);
	close_exit:
			if (devh)
				libusb_close(devh);
			if (keep_running)
				sleep(1);
		} while (keep_running);
	}

release_exit:
	libusb_exit(NULL);
	return ret;
}
Esempio n. 8
0
RESPONSECODE IFDHCreateChannel ( DWORD Lun, DWORD Channel ) {

    //RESPONSECODE IO_Create_Channel ( DWORD Channel ) {
    //DWORD Lun = 0;

  /* Lun - Logical Unit Number, use this for multiple card slots 
     or multiple readers. 0xXXXXYYYY -  XXXX multiple readers,
     YYYY multiple slots. The resource manager will set these 
     automatically.  By default the resource manager loads a new
     instance of the driver so if your reader does not have more than
     one smartcard slot then ignore the Lun in all the functions.
     Future versions of PC/SC might support loading multiple readers
     through one instance of the driver in which XXXX would be important
     to implement if you want this.
  */
  
  /* Channel - Channel ID.  This is denoted by the following:
     0x000001 - /dev/pcsc/1
     0x000002 - /dev/pcsc/2
     0x000003 - /dev/pcsc/3
     
     USB readers may choose to ignore this parameter and query 
     the bus for the particular reader.
  */

  /* This function is required to open a communications channel to the 
     port listed by Channel.  For example, the first serial reader on COM1 would
     link to /dev/pcsc/1 which would be a sym link to /dev/ttyS0 on some machines
     This is used to help with intermachine independance.
     
     Once the channel is opened the reader must be in a state in which it is possible
     to query IFDHICCPresence() for card status.
 
     returns:

     IFD_SUCCESS
     IFD_COMMUNICATION_ERROR
  */

  syslog(LOG_INFO, "This is the Myson driver");
  srand(time(0));
  
  int readerNum = (Lun & 0xFFFF0000) >> 16;
  
  libusb_context *context;
  if(libusb_init(&context) != 0) //unable to initialize libusb
  {
    syslog(LOG_INFO, "Unable to initialize libusb");
    return IFD_COMMUNICATION_ERROR;
  }
  rd[readerNum].context = context;
  
  rd[readerNum].handle = libusb_open_device_with_vid_pid(context, 0x04cf, 0x9920);
  syslog(LOG_INFO, "Success");
  
  if(rd[readerNum].handle == NULL)
  {
    syslog(LOG_INFO, "Did you connect the Myson?");
    return IFD_COMMUNICATION_ERROR;
  }
  
  libusb_device* dev = libusb_get_device(rd[readerNum].handle);
  
  //avoid conflict with an existing mass storage driver
  //this function, although it is in the documentation, is absent from libusb.h...
  //libusb_set_auto_detach_kernel_driver(rd[readerNum].handle,1);
  
  //we will claim the interface
  if(libusb_kernel_driver_active(rd[readerNum].handle,0) == 1) //then we free it
  {
    if(libusb_detach_kernel_driver(rd[readerNum].handle,0) != 0) //error when freeing?
    {
      syslog(LOG_INFO, "Unable to detach interface from kernel driver");
      libusb_close(rd[readerNum].handle);
      libusb_exit(context);
      return IFD_COMMUNICATION_ERROR;
    }
  }
  if(libusb_claim_interface(rd[readerNum].handle, 0) != 0)
  {
    syslog(LOG_INFO, "Unable to claim interface");
    libusb_close(rd[readerNum].handle);
    libusb_exit(context);
    return IFD_COMMUNICATION_ERROR;
  }

  syslog(LOG_INFO, "Myson successfully initialized");
  int maxsize = libusb_get_max_packet_size(dev, IN_ENDPOINT);
  printf("Max IN packet size: %d\n", maxsize);
  maxsize = libusb_get_max_packet_size(dev, OUT_ENDPOINT);
  printf("Max OUT packet size: %d\n", maxsize);
  
  return IFD_SUCCESS;
}
Esempio n. 9
0
int initialize(void){
  int r=1;
  int i=0;
  int cnt=0;
  /* libusb initialize*/
  if ((r = libusb_init(&ctx)) < 0) {
    perror("libusb_init\n");
    exit(1);
  } else {
    libusb_set_debug(ctx,3);
    Dprintf("init done\n");
  }  
  
  /* confirm powerusb device */
  /* list up all usb devices */
  if((libusb_get_device_list(ctx,&devs)) < 0) {
    perror("no usb device found");
    exit(1);
  }
  /* check every usb devices */
  while((dev =devs[i++]) != NULL) {
    struct libusb_device_descriptor desc;
    if (libusb_get_device_descriptor(dev,&desc) < 0) {
      perror("failed to get device descriptor\n");
      return 1;
    }
    /* count how many PowerUSB device connected */
    if (desc.idVendor == USB_VENDOR_ID &&
	desc.idProduct == USB_PRODUCT_ID) {
      cnt++;
      Dprintf("PowerUSB device found\n");
    }
  }
  /* no PowerUSB found*/
  if (cnt == 0) {
    fprintf(stderr, "Power USB device not connected\n");
    exit(1);
  }
  /* multi-PowerUSB device found: return error*/
  if (cnt > 1) {
    /* FIXME */
    fprintf(stderr, "multi PowerUSB is not implemented yet\n");
    exit(1);
  }


  /* open powerusb device */
  if ((devh = libusb_open_device_with_vid_pid(ctx,USB_VENDOR_ID,
					      USB_PRODUCT_ID)) < 0 ) {
    perror("can't find PowerUSB device\n");
    finalize();
    exit(1);
  } else {
    Dprintf("PowerUSB device opened\n");
  }

  /* detach kernel driver if attached. */
  /* is kernel driver active?*/
  r = libusb_kernel_driver_active(devh,0);
  if (r == 1) {
    /*detaching kernel driver*/
    r = libusb_detach_kernel_driver(devh,0);
    if (r != 0) {
      perror("detaching kernel driver failed");
      exit(1);
    }
  }
  return 0;
}
Esempio n. 10
0
int
gp_port_library_list (GPPortInfoList *list)
{
	GPPortInfo	info;
	int		nrofdevices = 0;
	int		d, i, i1, i2, unknownint;
	libusb_context	*ctx;
	libusb_device	**devs = NULL;
	int		nrofdevs = 0;
	struct libusb_device_descriptor	*descs;

	C_LIBUSB (libusb_init (&ctx), GP_ERROR_IO);

	/* TODO: make sure libusb_exit gets called in all error paths inside this function */

	/* generic matcher. This will catch passed XXX,YYY entries for instance. */
	C_GP (gp_port_info_new (&info));
	gp_port_info_set_type (info, GP_PORT_USB);
	gp_port_info_set_name (info, "");
	gp_port_info_set_path (info, "^usb:");
	gp_port_info_list_append (list, info); /* do not check return value, it might be -1 */

	nrofdevs = libusb_get_device_list (ctx, &devs);
	C_MEM (descs = calloc (nrofdevs, sizeof(descs[0])));
	for (i=0;i<nrofdevs;i++)
		LOG_ON_LIBUSB_E (libusb_get_device_descriptor(devs[i], &descs[i]));

	for (d = 0; d < nrofdevs; d++) {
		/* Devices which are definitely not cameras. */
		if (	(descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
			(descs[d].bDeviceClass == LIBUSB_CLASS_COMM)	||
			(descs[d].bDeviceClass == 0xe0)	/* wireless / bluetooth */
		)
			continue;
		/* excepts HUBs, usually the interfaces have the classes, not
		 * the device */
		unknownint = 0;
		for (i = 0; i < descs[d].bNumConfigurations; i++) {
			struct libusb_config_descriptor *config;

			if (LOG_ON_LIBUSB_E (libusb_get_config_descriptor (devs[d], i, &config))) {
				unknownint++;
				continue;
			}
			for (i1 = 0; i1 < config->bNumInterfaces; i1++)
				for (i2 = 0; i2 < config->interface[i1].num_altsetting; i2++) {
					const struct libusb_interface_descriptor *intf = &config->interface[i1].altsetting[i2]; 
					if (	(intf->bInterfaceClass == LIBUSB_CLASS_HID)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_PRINTER)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_COMM)	||
						(intf->bInterfaceClass == 0xe0)	/* wireless/bluetooth*/
					)
						continue;
					unknownint++;
				}
			libusb_free_config_descriptor (config);
		}
		/* when we find only hids, printer or comm ifaces  ... skip this */
		if (!unknownint)
			continue;
		/* Note: We do not skip USB storage. Some devices can support both,
		 * and the Ricoh erronously reports it.
		 */ 
		nrofdevices++;
	}

#if 0
	/* If we already added usb:, and have 0 or 1 devices we have nothing to do.
	 * This should be the standard use case.
	 */
	/* We never want to return just "usb:" ... also return "usb:XXX,YYY", and
	 * let upper layers filter out the usb: */
	if (nrofdevices <= 1) 
		return (GP_OK);
#endif

	/* Redo the same bus/device walk, but now add the ports with usb:x,y notation,
	 * so we can address all USB devices.
	 */
	for (d = 0; d < nrofdevs; d++) {
		char path[200];

		/* Devices which are definitely not cameras. */
		if (	(descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
			(descs[d].bDeviceClass == LIBUSB_CLASS_COMM)
		)
			continue;
		/* excepts HUBs, usually the interfaces have the classes, not
		 * the device */
		unknownint = 0;
		for (i = 0; i < descs[d].bNumConfigurations; i++) {
			struct libusb_config_descriptor *config;

			if (LOG_ON_LIBUSB_E (libusb_get_config_descriptor (devs[d], i, &config))) {
				unknownint++;
				continue;
			}
			for (i1 = 0; i1 < config->bNumInterfaces; i1++)
				for (i2 = 0; i2 < config->interface[i1].num_altsetting; i2++) {
					const struct libusb_interface_descriptor *intf = &config->interface[i1].altsetting[i2]; 
					if (	(intf->bInterfaceClass == LIBUSB_CLASS_HID)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_PRINTER)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_COMM))
						continue;
					unknownint++;
				}
			libusb_free_config_descriptor (config);
		}
		/* when we find only hids, printer or comm ifaces  ... skip this */
		if (!unknownint)
			continue;
		/* Note: We do not skip USB storage. Some devices can support both,
		 * and the Ricoh erronously reports it.
		 */ 
		C_GP (gp_port_info_new (&info));
		gp_port_info_set_type (info, GP_PORT_USB);
		gp_port_info_set_name (info, "Universal Serial Bus");
		snprintf (path,sizeof(path), "usb:%03d,%03d",
			libusb_get_bus_number (devs[d]),
			libusb_get_device_address (devs[d])
		);
		gp_port_info_set_path (info, path);
		C_GP (gp_port_info_list_append (list, info));
	}

	libusb_free_device_list (devs, 1);
	libusb_exit (ctx); /* should free all stuff above */
	free (descs);

	/* This will only be added if no other device was ever added.
	 * Users doing "usb:" usage will enter the regular expression matcher case. */
	if (nrofdevices == 0) {
		C_GP (gp_port_info_new (&info));
		gp_port_info_set_type (info, GP_PORT_USB);
		gp_port_info_set_name (info, "Universal Serial Bus");
		gp_port_info_set_path (info, "usb:");
		C_GP (gp_port_info_list_append (list, info));
	}
	return (GP_OK);
}
Esempio n. 11
0
int main(int argc, char **argv)
{
    if(argc <= 1)
        usage();
    int ret = 0;
    libusb_init(NULL);
    libusb_device_handle *dev = libusb_open_device_with_vid_pid(NULL, 0x601a, 0x4760);
    if(dev == NULL)
    {
        printf("Cannot open device\n");
        return -1;
    }
    if(libusb_claim_interface(dev, 0) != 0)
    {
        printf("Cannot claim interface\n");
        libusb_close(dev);
        return -2;
    }

    enum
    {
        OPT_ADDR = 0x100, OPT_LENGTH, OPT_UPLOAD, OPT_CPUINFO, OPT_DOWNLOAD,
        OPT_START1, OPT_WAIT, OPT_RENUMERATE, OPT_START2, OPT_FLUSH_CACHES,
        OPT_S1_ADDR, OPT_STAGE1
    };
    unsigned long last_length = 0;
    unsigned long s1_addr = 0x80000000;
    while(1)
    {
        static struct option long_options[] =
        {
            {"help", no_argument, 0, 'h'},
            {"cpuinfo", no_argument, 0, OPT_CPUINFO},
            {"addr", required_argument, 0, OPT_ADDR},
            {"length", required_argument, 0, OPT_LENGTH},
            {"upload", required_argument, 0, OPT_UPLOAD},
            {"download", required_argument, 0, OPT_DOWNLOAD},
            {"start1", required_argument, 0, OPT_START1},
            {"wait", required_argument, 0, OPT_WAIT},
            {"renumerate", no_argument, 0, OPT_RENUMERATE},
            {"start2", required_argument, 0, OPT_START2},
            {"flush-caches", no_argument, 0, OPT_FLUSH_CACHES},
            {"s1-addr", required_argument, 0, OPT_S1_ADDR},
            {"stage1", required_argument, 0, OPT_STAGE1},
            {0, 0, 0, 0}
        };

        int c = getopt_long(argc, argv, "hv", long_options, NULL);
        char *end = 0;
        unsigned long param;
        if(c == OPT_ADDR || c == OPT_LENGTH || c == OPT_START1 || c == OPT_WAIT
                || c == OPT_S1_ADDR)
        {
            param = strtoul(optarg, &end, 0);
            if(*end)
            {
                printf("Invalid argument '%s'\n", optarg);
                ret = 1;
                break;
            }
        }
        if(c == -1)
            break;
        switch(c)
        {
            default:
            case -1:
                break;
            case 'h':
                usage();
                break;
            case 'v':
                g_verbose = true;
                break;
            case OPT_ADDR:
                ret = jz_set_addr(dev, param);
                break;
            case OPT_LENGTH:
                last_length = param;
                ret = jz_set_length(dev, param);
                break;
            case OPT_UPLOAD:
                ret = jz_upload(dev, optarg, last_length);
                break;
            case OPT_DOWNLOAD:
                ret = jz_download(dev, optarg);
                break;
            case OPT_CPUINFO:
                ret = jz_cpuinfo(dev);
                break;
            case OPT_START1:
                ret = jz_start1(dev, param);
                break;
            case OPT_WAIT:
                if(g_verbose)
                    printf("Wait for %lu seconds...\n", param);
                sleep(param);
                break;
            case OPT_RENUMERATE:
                ret = renumerate(&dev);
                break;
            case OPT_START2:
                ret = jz_start2(dev, param);
                break;
            case OPT_FLUSH_CACHES:
                ret = jz_flush_caches(dev);
                break;
            case OPT_S1_ADDR:
                s1_addr = param;
                break;
            case OPT_STAGE1:
                ret = jz_stage1(dev, s1_addr, optarg);
                break;
        }
        if(ret != 0)
            break;
    }
    if(optind != argc)
    {
        printf("Error: extra arguments on command line\n");
        ret = 1;
    }

    libusb_close(dev);
    libusb_exit(NULL);
    return ret;
}
int main (int argc, char **argv)
{
  bool daemonize = false;

  while (true) {
      int c;
      static struct option long_options[] =
          {
              {"help",    no_argument, NULL, 'h'},
              {"version", no_argument, NULL, 'v'},
              {"daemon",  no_argument, NULL, 'd'},
              {"fork",    no_argument, NULL, 'f'},
              {0, 0, 0, 0}
          };

      c = getopt_long(argc, argv, "hvd", long_options, NULL);
      if (c == -1)
        break;
      switch (c) {
      case 'h':
        print_usage(argv[0]);
        exit(EXIT_SUCCESS);
      case 'v':
        msg("HAMA MCE remote event client v%s for XBMC\n", VERSION);
        exit(EXIT_SUCCESS);
      case 'd':
        daemonize = true;
        break;
      default:
        print_usage(argv[0]);
        exit(EXIT_FAILURE);
      }
  }

  if (optind < (argc - 1)) {
      err("%s: too many arguments\n", argv[0]);
      exit(EXIT_FAILURE);
  }

  struct sigaction sa;
  sigemptyset(&sa.sa_mask);
  sa.sa_handler = handle_exit;
  PCHK(sigaction(SIGINT,  &sa, NULL));
  PCHK(sigaction(SIGTERM, &sa, NULL));

  libusb_context *ctx;
  libusb_device_handle *dev;
  struct libusb_transfer *transfer0x81 = libusb_alloc_transfer(0);
  struct libusb_transfer *transfer0x82 = libusb_alloc_transfer(0);
  unsigned char buf0x81 [8];
  unsigned char buf0x82 [5];

  UCHK(libusb_init(&ctx));

  if (!(dev = libusb_open_device_with_vid_pid(ctx, 0x05a4, 0x9881))) {
      err("%s: No HAMA MCE remote control found.\n", argv[0]);
      exit(EXIT_FAILURE);
  }

  int exit_code = EXIT_SUCCESS;

  if (libusb_kernel_driver_active(dev, 0))
    UCHK(libusb_detach_kernel_driver(dev, 0));
  if (libusb_kernel_driver_active(dev, 1))
    UCHK(libusb_detach_kernel_driver(dev, 1));
  UCHK(libusb_claim_interface(dev, 0));
  UCHK(libusb_claim_interface(dev, 1));

  libusb_fill_interrupt_transfer(transfer0x81, dev, 0x81, buf0x81, sizeof(buf0x81), transfer0x81_cb, NULL, 215);
  UCHK(libusb_submit_transfer(transfer0x81));

  libusb_fill_interrupt_transfer(transfer0x82, dev, 0x82, buf0x82, sizeof(buf0x82), transfer0x82_cb, NULL, 200);
  UCHK(libusb_submit_transfer(transfer0x82));

  msg("Connected HAMA MCE Remote\n");
  xbmc.SendHELO("HAMA MCE Remote", ICON_NONE);

  if (daemonize) {
      if (daemon(0,0) == -1) {
          err("Failed to fork\n");
          perror(argv[0]);
          exit_code = EXIT_FAILURE;
          goto exit;
      }
  }

  while (!(disconnected || quit)) {
      UCHK(libusb_handle_events(ctx));
  }
  exit:
  if (disconnected) {
      msg("Disconnected HAMA MCE Remote\n");
      xbmc.SendNOTIFICATION("Disconnected", "HAMA MCE Remote", ICON_NONE);
  }
  else {
      msg("Closing HAMA MCE Remote\n");
      xbmc.SendNOTIFICATION("Closing", "HAMA MCE Remote", ICON_NONE);
  }

  libusb_free_transfer(transfer0x81);
  libusb_free_transfer(transfer0x82);

  if (!disconnected) {
      // Release the remote back to the system
      UCHK(libusb_release_interface(dev, 0));
      UCHK(libusb_release_interface(dev, 1));
      UCHK(libusb_attach_kernel_driver(dev, 0));
      UCHK(libusb_attach_kernel_driver(dev, 1));
  }

  libusb_close(dev);
  libusb_exit(ctx);

  exit(exit_code);
}
Esempio n. 13
0
fx2::fx2():dev_handle(NULL) {

 int rv=libusb_init(&libusb_ctx);
 assert(!rv);
 libusb_set_debug(libusb_ctx,0);
}
int main(int argc, char **argv) {
  reset_wacom_inkling();
  
  const struct libusb_version *version = libusb_get_version();
  printf("Using libusb v%d.%d.%d.%d\n\n", version->major, version->minor, version->micro, version->nano);

  int r=1;

  r = libusb_init(NULL);
  if (r < 0) {
    fprintf(stderr, "Failed to initialise libusb\n");
    return 1;
  }

  // discover devices
  libusb_device **list;
  libusb_device *found = NULL;
  libusb_context *ctx = NULL;
  int attached = 0;

  ssize_t cnt = libusb_get_device_list(ctx, &list);
  ssize_t i = 0;
  int err = 0;
  if (cnt < 0){
    printf( "no usb devices found\n" );
    goto out;
  }

  // find our device
  for(i = 0; i < cnt; i++){
    libusb_device *device = list[i];
    struct libusb_device_descriptor desc;
    int r = libusb_get_device_descriptor( device, &desc );

    if( desc.idVendor == VENDOR_ID && desc.idProduct == PRODUCT_ID ){
      found=device;
    }
  }

  if (found == NULL){
    printf("Unable to find usb device\n");
    goto out;
  }

  libusb_device_handle *devh; 
  err = libusb_open(found, &devh);
  if (err){
    printf("Unable to open usb device\n");
    goto out;
  }

  printf("Successfully find device\n");

//#ifdef LINUX 
  if (libusb_kernel_driver_active(devh,0)==1){
    printf("Device busy...detaching...\n"); 
    attached = 1;
    libusb_detach_kernel_driver(devh, 0);   
  }
//#endif 


  err = libusb_claim_interface( devh, 0 );
  if (err){
    printf( "Failed to claim interface. " );
    switch( err ){
    case LIBUSB_ERROR_NOT_FOUND:	
      printf( "not found\n" );	break;
    case LIBUSB_ERROR_BUSY:		
      printf( "busy\n" );		break;
    case LIBUSB_ERROR_NO_DEVICE:	
      printf( "no device\n" );	break;
    default:			
      printf( "other\n" );		break;
    }
    goto out;
  } 
  printf( "interface claimed\n" );


  {//important to enable device, buf[4]=1 will enable output while 2 will disable
   //seems only 1 and 2 are valid from reading function
    char buf[]={0x80,0x01,0x02,0x01,0x02};
    send_control_transfer(devh,buf,sizeof(buf));
  }  

  {//I guess it is setting ID. 01 is mouse and 02 are digitizer,
   //04 is undefined but looks like raw data we want. 08 has too many data that crash RPi, won't listen to 128
    int report_id_setting=4;
    char buf[]={0x80,0x01,0x03,0x01,report_id_setting};
    send_control_transfer(devh,buf,sizeof(buf));
  }

  {//read back report id settings
    char buf[]={0x80,0x01,0x0A,0x01,0x01,0x03,0x01};
    send_control_transfer(devh,buf,sizeof(buf));
  }
  receive_control_transfer(devh);

  {//not sure what this is but seems important 
    char buf[]={0x80,0x01,0x0B,0x01};
    send_control_transfer(devh,buf,sizeof(buf));
  }

  {//re-enable output
    char buf[]={0x80,0x01,0x02,0x01,0x01};
    send_control_transfer(devh,buf,sizeof(buf));
  }
  
  printf("Yeah\n");

  int bytes_transferred;

  while(1){
    r = libusb_bulk_transfer(devh,0x83,data_in,16,&bytes_transferred,TIMEOUT_MS);
    switch(r){
	case 0:	//success
	  {
	    if (data_in[0]==2){
	      int x=data_in[1]+data_in[2]*256;
	      int y=data_in[3]+data_in[4]*256;
	      int button=data_in[5];
	      int pressure=data_in[6]+data_in[7]*256;
	      int x_tilt=(signed char)data_in[8];
	      int y_tilt=(signed char)data_in[9];
		
	      printf("x:%d\ty:%d\tb:%d\tp:%d\txt:%d\tyt:%d\n",x,y,button,pressure,x_tilt,y_tilt);
	    }else if (data_in[0]==4){
	      int x=data_in[3]+data_in[2]*256;	//ignore the 3rd byte
	      if (x>32767) x=x-65536;
	      int y=data_in[6]+data_in[5]*256;
	      int button=data_in[7];
	      int pressure=data_in[8]+data_in[9]*256;
	      int x_tilt=(signed char)data_in[10];
	      int y_tilt=(signed char)data_in[11];
	      static int button_last=0;
	      if (debug_output){
		printf("x:%d\ty:%d\tb:%d\tp:%d\txt:%d\tyt:%d\n",x,y,button,pressure,x_tilt,y_tilt);
	      }else{
		if (button!=0){
		  printf("d:%d %d\n",x,y);
		}else{
		  if (button_last!=0){
		    printf("u:\n");
		    fflush(stdout);
		  }
		}
	      }
	      button_last=button;
	    }else{
	      if (debug_output){
		for(i = 0; i < bytes_transferred; i++){
		  printf("%02x ",data_in[i]);
		}
		printf("\n");
	      }
	    }
	  }
	  
	  break;
	  
    case LIBUSB_ERROR_TIMEOUT :	
      printf( "LIBUSB_ERROR_TIMEOUT (Don't worry)\n" );	break;
    case LIBUSB_ERROR_PIPE :		
      printf( "LIBUSB_ERROR_PIPE \n" );		break;
    case LIBUSB_ERROR_OVERFLOW :	
      printf( "no LIBUSB_ERROR_OVERFLOW \n" );	break;
    case LIBUSB_ERROR_NO_DEVICE :	
      printf( "no LIBUSB_ERROR_NO_DEVICE \n" );	break;
    default:			
      printf( "other\n" );		break;
    } 
  }	
out:
  //libusb_reset_device(devh);
  libusb_close(devh);
  libusb_exit(NULL);

  return 0;
}
Esempio n. 15
0
fx3_dev_err_t FX3Dev::init(const char* firmwareFileName /* = NULL */, const char* additionalFirmwareFileName /* = NULL */ ) {
    int ires = libusb_init( &ctx );
    if ( ires != 0 ) {
        fprintf( stderr, "FX3Dev::Init(): __error__ libusb_init, code %d %s\n", ires, libusb_error_name( ires ) );
        return FX3_ERR_USB_INIT_FAIL;
    }

    libusb_set_debug( ctx, FX3_DEBUG_LEVEL_DEFAULT );

    scan();

    fx3_dev_err_t eres = FX3_ERR_OK;

    if ( endpoint_from_dev_num == endpoint_invalid ) {
        fprintf( stderr, "FX3Dev::Init() asked to flash firmware. Looking for device without firmware (pid = 0x%04x)\n", DEV_PID_FOR_FW_LOAD );
        device_handle = libusb_open_device_with_vid_pid( ctx, VENDOR_ID, DEV_PID_FOR_FW_LOAD );
        if( device_handle != NULL ) {
            fprintf( stderr, "FX3Dev::Init() Found device. Will flash it with firmware from file '%s'\n", firmwareFileName );
            eres = firmwareFlashFromFile( firmwareFileName );
            if ( eres == FX3_ERR_OK ) {
                fprintf( stderr, "FX3Dev::Init() flash completed!\nPlease wait for %d seconds\n", PAUSE_AFTER_FLASH_SECONDS );
                for ( int i = 0; i < PAUSE_AFTER_FLASH_SECONDS * 2; i++ ) {
                    #ifdef WIN32
                    Sleep( 500 );
                    #else
                    usleep( 500000 );
                    #endif
                    fprintf( stderr, "*" );
                }
                fprintf( stderr, "\n" );
                libusb_close(device_handle);
                device_handle = NULL;
                
                scan();
                
            } else {
                fprintf( stderr, "FX3Dev::Init() __error__ flash failed, error %d %s\n", eres, fx3_get_error_string( eres ) );
                return eres;
            }
        } else {
            fprintf( stderr, "FX3Dev::Init() no device without firmware found. Maybe already flashed?\n" );
        }
        last_overflow_count = 0;
    }
    
    if ( endpoint_from_dev_num == endpoint_invalid ) {
        fprintf( stderr, "FX3Dev::Init() Device don't have endpoint with stream data to host!\n" );
        return FX3_ERR_BAD_DEVICE;
    }
    
    fprintf( stderr, "FX3Dev::Init() Proceed to init flashed device (0x%04x)\n", DEV_PID_NO_FW_NEEDED );
    
    device_handle = libusb_open_device_with_vid_pid( ctx, VENDOR_ID, DEV_PID_NO_FW_NEEDED );
    
    if ( device_handle == NULL ) {
        fprintf( stderr, "FX3Dev::Init() __error__ no device with vid = 0x%04x and pid = 0x%04X found!\n", VENDOR_ID, DEV_PID_NO_FW_NEEDED );
        return FX3_ERR_NO_DEVICE_FOUND;
    }
    
    if ( additionalFirmwareFileName != NULL ) {
        if ( additionalFirmwareFileName[ 0 ] != 0 ) {
            eres = loadAdditionalFirmware( additionalFirmwareFileName, 48 );
            if ( eres != FX3_ERR_OK ) {
                fprintf( stderr, "FX3Dev::Init() __error__ loadAdditionalFirmware %d %s\n", eres, fx3_get_error_string( eres ) );
                return eres;
            } else {
                fprintf( stderr, "loadAdditionalFirmware ok\n" );
            }
        }
    }
    readFwVersion();

    ires = libusb_claim_interface(device_handle, 0);
    if ( ires < 0 ) {
        fprintf( stderr, "FX3Dev::Init() __error__ libusb_claim_interface failed %d %s\n", ires, libusb_error_name( ires ) );
        return FX3_ERR_USB_INIT_FAIL;
    }
    
    return FX3_ERR_OK;
}
Esempio n. 16
0
int main(int argc, char **argv)
{
	struct sigaction sigact;
	int r = 1;

	parse_args(argc, argv);

	sigact.sa_handler = sighandler_exit;
	sigemptyset(&sigact.sa_mask);
	sigact.sa_flags = 0;
	sigaction(SIGINT, &sigact, NULL);
	sigaction(SIGTERM, &sigact, NULL);
	sigaction(SIGQUIT, &sigact, NULL);
	sigact.sa_handler = sighandler_wait_child;
	sigaction(SIGCHLD, &sigact, NULL);

	if (logfile != NULL) {
		set_wmlogger(argv[0], WMLOGGER_FILE, logfile);
	} else if (daemonize) {
		set_wmlogger(argv[0], WMLOGGER_SYSLOG, NULL);
	} else {
		set_wmlogger(argv[0], WMLOGGER_FILE, stderr);
	}

	if (daemonize) {
		daemon(0, 0);
	}

	r = libusb_init(&ctx);
	if (r < 0) {
		wmlog_msg(0, "failed to initialise libusb");
		exit_release_resources(1);
	}

	devh = find_wimax_device();
	if (devh == NULL) {
		wmlog_msg(0, "Could not find/open device");
		exit_release_resources(1);
	}

	wmlog_msg(0, "Device found");

	if (detach_dvd && libusb_kernel_driver_active(devh, IF_DVD) == 1) {
		r = libusb_detach_kernel_driver(devh, IF_DVD);
		if (r < 0) {
			wmlog_msg(0, "kernel driver detach error %d", r);
		} else {
			wmlog_msg(0, "detached pseudo-DVD kernel driver");
		}
	}

	if (libusb_kernel_driver_active(devh, IF_MODEM) == 1) {
		kernel_driver_active = 1;
		r = libusb_detach_kernel_driver(devh, IF_MODEM);
		if (r < 0) {
			wmlog_msg(0, "kernel driver detach error %d", r);
		} else {
			wmlog_msg(0, "detached modem kernel driver");
		}
	}

	r = libusb_claim_interface(devh, IF_MODEM);
	if (r < 0) {
		wmlog_msg(0, "Claim usb interface error %d", r);
		exit_release_resources(1);
	}
	wmlog_msg(0, "Claimed interface");

	alloc_fds();
	libusb_set_pollfd_notifiers(ctx, cb_add_pollfd, cb_remove_pollfd, NULL);

	r = init();
	if (r < 0) {
		wmlog_msg(0, "init error %d", r);
		exit_release_resources(1);
	}

	if_create();
	cb_add_pollfd(tap_fd, POLLIN, NULL);

	r = scan_loop();
	if (r < 0) {
		wmlog_msg(0, "scan_loop error %d", r);
		exit_release_resources(1);
	}

	exit_release_resources(0);
	return 0;
}
Esempio n. 17
0
//
// main
// ----
//
int main(void)
{
    libusb_device **devs;
    int r; // holds return codes
    ssize_t cnt;
    libusb_device* dev;
    libusb_device_handle* handle;

    int weigh_count = WEIGH_COUNT -1;

    //
    // We first try to init libusb.
    //
    r = libusb_init(NULL);
    // 
    // If `libusb_init` errored, then we quit immediately.
    //
    if (r < 0)
        return r;

#ifdef DEBUG
        libusb_set_debug(NULL, 3);
#endif

    //
    // Next, we try to get a list of USB devices on this computer.
    cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0)
        return (int) cnt;

    //
    // Once we have the list, we use **find_scale** to loop through and match
    // every device against the scales.h list. **find_scale** will return the
    // first device that matches, or 0 if none of them matched.
    //
    dev = find_scale(devs);
    if(dev == 0) {
        fprintf(stderr, "No USB scale found on this computer.\n");
        return -1;
    }
    
    //
    // Once we have a pointer to the USB scale in question, we open it.
    //
    r = libusb_open(dev, &handle);
    //
    // Note that this requires that we have permission to access this device.
    // If you get the "permission denied" error, check your udev rules.
    //
    if(r < 0) {
        if(r == LIBUSB_ERROR_ACCESS) {
            fprintf(stderr, "Permission denied to scale.\n");
        }
        else if(r == LIBUSB_ERROR_NO_DEVICE) {
            fprintf(stderr, "Scale has been disconnected.\n");
        }
        return -1;
    }
    //
    // On Linux, we typically need to detach the kernel driver so that we can
    // handle this USB device. We are a userspace tool, after all.
    //
#ifdef __linux__
    libusb_detach_kernel_driver(handle, 0);
#endif
    //
    // Finally, we can claim the interface to this device and begin I/O.
    //
    libusb_claim_interface(handle, 0);



    /*
     * Try to transfer data about status
     *
     * http://rowsandcolumns.blogspot.com/2011/02/read-from-magtek-card-swipe-reader-in.html
     */
    unsigned char data[WEIGH_REPORT_SIZE];
    int len;
    int scale_result = -1;
    
    //
    // For some reason, we get old data the first time, so let's just get that
    // out of the way now. It can't hurt to grab another packet from the scale.
    //
    r = libusb_interrupt_transfer(
        handle,
        //bmRequestType => direction: in, type: class,
                //    recipient: interface
        LIBUSB_ENDPOINT_IN | //LIBUSB_REQUEST_TYPE_CLASS |
            LIBUSB_RECIPIENT_INTERFACE,
        data,
        WEIGH_REPORT_SIZE, // length of data
        &len,
        10000 //timeout => 10 sec
        );
    // 
    // We read data from the scale in an infinite loop, stopping when
    // **print_scale_data** tells us that it's successfully gotten the weight
    // from the scale, or if the scale or transmissions indicates an error.
    //
    for(;;) {
        //
        // A `libusb_interrupt_transfer` of 6 bytes from the scale is the
        // typical scale data packet, and the usage is laid out in *HID Point
        // of Sale Usage Tables*, version 1.02.
        //
        r = libusb_interrupt_transfer(
            handle,
            //bmRequestType => direction: in, type: class,
                    //    recipient: interface
            LIBUSB_ENDPOINT_IN | //LIBUSB_REQUEST_TYPE_CLASS |
                LIBUSB_RECIPIENT_INTERFACE,
            data,
            WEIGH_REPORT_SIZE, // length of data
            &len,
            10000 //timeout => 10 sec
            );
        // 
        // If the data transfer succeeded, then we pass along the data we
        // received tot **print_scale_data**.
        //
        if(r == 0) {
#ifdef DEBUG
            int i;
            for(i = 0; i < WEIGH_REPORT_SIZE; i++) {
                printf("%x\n", data[i]);
            }
#endif
            if (weigh_count < 1) {
                scale_result = print_scale_data(data);
                if(scale_result != 1)
                   break;
            }
            weigh_count--;
        }
        else {
            fprintf(stderr, "Error in USB transfer\n");
            scale_result = -1;
            break;
        }
    }
    
    // 
    // At the end, we make sure that we reattach the kernel driver that we
    // detached earlier, close the handle to the device, free the device list
    // that we retrieved, and exit libusb.
    //
#ifdef __linux__
    libusb_attach_kernel_driver(handle, 0);
#endif
    libusb_close(handle);
    libusb_free_device_list(devs, 1);
    libusb_exit(NULL);

    // 
    // The return code will be 0 for success or -1 for errors (see
    // `libusb_init` above if it's neither 0 nor -1).
    // 
    return scale_result;
}
Esempio n. 18
0
int
open_sr16(void)
{
	libusb_device **devs;
	int r;
	int rval = -1;
	ssize_t cnt;
	libusb_device *dev;
	struct libusb_device_descriptor desc;
	
	struct libusb_config_descriptor *config;
	int transfered;
	
	char buffer[256];
	r = libusb_init(NULL );
	if (r < 0)
	{
		return r;
	}
	libusb_set_debug(NULL, 4);
	
	cnt = libusb_get_device_list(NULL, &devs);
	if ( cnt < 0 )
	{
		return (int) cnt;
	}
	
	// print_devs(devs);
	dev = find_dev(devs, 0x0763, 0x0150 );
	if ( dev )
	{
		libusb_get_device_descriptor(dev, &desc);
		r = libusb_open(dev, &sr16_devh );
		/*
		printf("bLength:\t%d\n", desc.bLength );
		printf("bcdUSB:\t%d\n", desc.bcdUSB );
		printf("bDeviceClass:\t%d\n", desc.bDeviceClass );
		printf("bDeviceSubClass:\t%d\n", desc.bDeviceSubClass );
		printf("bDeviceProtocol:\t%d\n", desc.bDeviceProtocol );
		printf("bMaxPacketSize0:\t%d\n", desc.bMaxPacketSize0 );
		printf("idVendor:\t%d\n", desc.idVendor );
		printf("idProduct:\t%d\n", desc.idProduct );
		printf("bcdDevice:\t%d\n", desc.bcdDevice );
		printf("iManufacturer:\t%d\n", desc.iManufacturer );
		printf("iProduct:\t%d\n", desc.iProduct );
		printf("iSerialNumber:\t%d\n", desc.iSerialNumber );
		printf("bNumConfigurations:\t%d\n", desc.bNumConfigurations );
		*/
		if ( r < 0 )
		{
			perror("loibusb_open" );
		}
		else
		{
			rval = 0;
			if ( desc.iManufacturer )
			{
				r = libusb_get_string_descriptor_ascii(sr16_devh, desc.iManufacturer, buffer, 255 );
				printf("Manufacturer:\t%s\n", buffer );
			}
			if ( desc.iProduct )
			{
				r = libusb_get_string_descriptor_ascii(sr16_devh, desc.iProduct, buffer, 255 );
				printf("Manufacturer:\t%s\n", buffer );
			}
			if ( desc.iSerialNumber )
			{
				r = libusb_get_string_descriptor_ascii(sr16_devh, desc.iSerialNumber, buffer, 255 );
				printf("Manufacturer:\t%s\n", buffer );
			}
			// Get the configuration
			/* r = libusb_get_config_descriptor(dev, 0, &config );
			if ( r )
			{
				perror("libusb_get_config_descriptor" );
			}
			else
			{
				printf("Config:\n" );
				printf("bLength:\t%d\n", config->bLength );
				printf("bDescriptorType:\t%d\n", config->bDescriptorType );
				printf("wTotalLength:\t%d\n", config->wTotalLength );
				printf("bNumInterfaces:\t%d\n", config->bNumInterfaces );
				printf("bConfigurationValue:\t%d\n", config->bConfigurationValue );
				printf("iConfiguration:\t%d\n", config->iConfiguration );
				printf("bmAttributes:\t%d\n", config->bmAttributes );
				printf("MaxPower:\t%d\n", config->MaxPower );
				printf("interface:\t%p\n", config->interface );
				printf("extra:\t%p\n", config->extra );
				printf("extra_length:\t%d\n", config->extra_length );
				libusb_free_config_descriptor(config );
			}
			*/		
		}
	}
	libusb_free_device_list(devs, 1);
	return rval;
}
Esempio n. 19
0
int setup_usb(void){
	int status;				//Holds status value for functions
	ssize_t	dev_cnt;			//Holds number of devices found

	//////////////////-Create libusb session
	status = libusb_init(&ctx);		//Create a libusb session
	if(status < 0){
		cout<<"Cannot create libusb session. Error: "<<status<<endl;
		exit(-2);
	}
	libusb_set_debug(ctx,3);		//Set verbosity to lvl 3
	//////////////////

	//////////////////-Available USB devices
	dev_cnt = libusb_get_device_list(ctx, &dev);	//Get list of USB devices

#ifdef USB_DEBUG
	if(dev_cnt < 0 ){
		cout<<"No USB devices found"<<endl;
	}
	ssize_t i;				//Search through device list
	for(i = 0; i < dev_cnt; i++){
		status = libusb_get_device_descriptor(dev[i], &desc);
		if(status < 0){
			cout<<"Failed to get device descriptor"<<endl;
			exit(-2);
		}
		if(desc.idVendor == SCROD_USB_VID && desc.idProduct == SCROD_USB_PID){
			cout<<"Found SCROD USB Device"<<endl;
			printdev(dev[i]);
			list_endpoints(dev[i]);
			break;
		}
	}
	if(i == dev_cnt){
		cout<<"Could not find SCROD USB Device"<<endl;
		exit(-2);
	}
#endif
	//////////////////

	//////////////////-Open USB device
	dev_handle = libusb_open_device_with_vid_pid(ctx,SCROD_USB_VID,SCROD_USB_PID);	//Open SCROD USB Device
	if(dev_handle == NULL){
		cout<<"Could not open SCROD USB Device"<<endl;
		exit(-2);
	}
	else{
		cout<<"SCROD USB Device Opened"<<endl;
	}
	libusb_free_device_list(dev,1);		//Unreferencing devices in device list as suggested in documentation
	//////////////////

	//////////////////-Check kernel status
	status = libusb_kernel_driver_active(dev_handle,0);
	if(status == 1){
		cout<<"Kernel driver active"<<endl;
		cout<<"Trying to detach driver..."<<endl;
		status = libusb_detach_kernel_driver(dev_handle,0);
		if(status == 0){
			cout<<"Kernel driver detached"<<endl;
		}
		else{
			cout<<"Kernel driver cannot be detached"<<endl;
			exit(-3);
		}
	}
	//////////////////

	//////////////////-Claim an interface
	status = libusb_claim_interface(dev_handle,0);
	if(status < 0){
		cout<<"Could not claim an interface"<<endl;
		exit(-3);
	}
	else{
		cout<<"Interface claimed"<<endl;
	}
	//////////////////
}
Esempio n. 20
0
std::unique_ptr<libusb_context, decltype(&libusb_exit)> usb_open() {
    libusb_context* p;
    usb_error::check(libusb_init(&p));
    return std::unique_ptr<libusb_context, decltype(&libusb_exit)>(p, libusb_exit);
}
Esempio n. 21
0
static int lusb_probe(struct bladerf_devinfo_list *info_list)
{
    int status, i, n;
    ssize_t count;
    libusb_device **list;
    struct bladerf_devinfo info;

    libusb_context *context;

    /* Initialize libusb for device tree walking */
    status = libusb_init(&context);
    if (status) {
        log_error("Could not initialize libusb: %s\n",
                  libusb_error_name(status));
        goto lusb_probe_done;
    }

    count = libusb_get_device_list(context, &list);
    /* Iterate through all the USB devices */
    for (i = 0, n = 0; i < count && status == 0; i++) {
        if (device_is_bladerf(list[i])) {
            log_verbose("Found bladeRF (based upon VID/PID)\n");

            /* Open the USB device and get some information */
            status = get_devinfo(list[i], &info);
            if (status) {
                /* We may not be able to open the device if another
                 * driver (e.g., CyUSB3) is associated with it. Therefore,
                 * just log to the debug level and carry on. */
                status = 0;
                log_debug("Could not open bladeRF device: %s\n",
                          libusb_error_name(status) );
            } else {
                info.instance = n++;
                status = bladerf_devinfo_list_add(info_list, &info);
                if( status ) {
                    log_error("Could not add device to list: %s\n",
                              bladerf_strerror(status) );
                } else {
                    log_verbose("Added instance %d to device list\n",
                                info.instance);
                }
            }
        }

        if (device_is_fx3_bootloader(list[i])) {
            status = get_devinfo(list[i], &info);
            if (status) {
                log_error("Could not open bladeRF device: %s\n",
                          libusb_error_name(status) );
                continue;
            }

            log_info("Found FX3 bootloader device on bus=%d addr=%d. This may "
                     "be a bladeRF.\nUse the bladeRF-cli command \"recover"
                     " %d %d <FX3 firmware>\" to boot the bladeRF firmware.\n",
                     info.usb_bus, info.usb_addr, info.usb_bus, info.usb_addr);
        }
    }

    libusb_free_device_list(list, 1);
    libusb_exit(context);

lusb_probe_done:
    return status;
}
Esempio n. 22
0
int main(int argc, char **argv) {
    const char *mode = "CGRAY";
    int resolution = 100;
    if(argc > 1) {
        switch(*argv[1]) {
            case 'c': mode = "CGRAY";  break;
            case 'g': mode = "GRAY64"; break;
            case 't': mode = "TEXT";   break;
            case '-': mode = NULL;     break;
            default:
                fprintf(stderr, "ERROR: unrecognised mode, "
                                "should be one of [cgt]\n");
                return 1;
        }
    }
    if(argc > 2) {
        resolution = atoi(argv[2]);
        if(resolution < 100 || resolution > 600 || resolution % 100) {
            fprintf(stderr, "ERROR: resolution must be a positive "
                            "multiple of 100 no greater than 600\n");
            return 1;
        }
    }

    libusb_context *context;
    libusb_init(&context);
    device_handle = libusb_open_device_with_vid_pid(context, VID, PID);
    if(!device_handle) {
        fprintf(stderr, "ERROR: Unable to find device "
                        "(Vendor ID = %04x, Product ID = %04x)\n",
                VID, PID);
        return 1;
    }
    libusb_claim_interface(device_handle, 0);
    libusb_set_interface_alt_setting(device_handle, 0, 0);

    control_in_vendor_device(1, 2, 0, 255); /* returns 05 10 01 02 00 */
    if(mode) {
        char *config = build_config(
                mode, MIN(resolution, 300), resolution,
                PAGE_WIDTH * MIN(resolution, 300)/100,
                PAGE_HEIGHT * resolution/100);
        send_config(config); free(config);
    }
    int page = 1;
    FILE *fp = NULL;
    int sleep_time = 0;
    while(1) {
        unsigned char buf[0x1000];
        int num_bytes = bulk_read(4, buf, 0x1000);
        if(num_bytes) sleep_time = 0;
        if(num_bytes > 2) {
            if(!fp) {
                char fname[8];
                snprintf(fname, 8, "%03d.raw", page);
                fprintf(stderr, "Opening '%s'...\n", fname);
                fp = fopen(fname, "wb");
            }
            fwrite(buf, 1, num_bytes, fp);
        } else if(num_bytes == 0 && sleep_time < 10) {
#ifdef DEBUG
            fprintf(stderr, "Sleeping\n");
#endif
            sleep_time++;
            usleep(200 * 1000);
        } else if(num_bytes == 2 && buf[0] == 0xc2 && buf[1] == 0x00) {
            fprintf(stderr, "ERROR: Nothing to scan\n"); break;
        } else if(num_bytes == 2 && buf[0] == 0xc3 && buf[1] == 0x00) {
            fprintf(stderr, "ERROR: Paper jam\n"); break;
        } else if(num_bytes == 1 && buf[0] == 0x80) {
            fprintf(stderr, "No more pages\n"); break;
        } else if((num_bytes == 1 && buf[0] == 0x81) || sleep_time >= 10) {
            fprintf(stderr, "Feeding in another page");
            if(sleep_time >= 10) fprintf(stderr, " (timeout)");
            fprintf(stderr, "\n");
            fclose(fp); fp = NULL;
            send_config("");
            page++;
            sleep_time = 0;
        } else if(num_bytes == 1 && buf[0] == 0xc3) {
            fprintf(stderr, "Paper jam\n"); break;
        } else if(num_bytes == 1 && buf[0] == 0xc4) {
            fprintf(stderr, "Scan aborted\n"); break;
        } else {
            fprintf(stderr, "Received unknown data: %02x", buf[0]);
            if(num_bytes == 2) fprintf(stderr, " %02x", buf[1]);
            fprintf(stderr, "\n");
            break;
        }
    }
    if(fp) fclose(fp);
    control_in_vendor_device(2, 2, 0, 255); /* returns 05 10 02 02 00 */

    libusb_release_interface(device_handle, 0);
    libusb_close(device_handle);
    libusb_exit(context);
    return 0;
}
Esempio n. 23
0
int main (int argc, char **argv)
{
	GOptionContext *context;
	GError *error = NULL;
	libusb_device **list;
	ssize_t num_devices, i;

	context = g_option_context_new ("- Manage Sixaxis PS3 controllers");
	g_option_context_add_main_entries (context, options, NULL);
	if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
		g_warning ("Couldn't parse command-line options: %s", error->message);
		return 1;
	}

	/* Check that the passed bdaddr is correct */
	if (option_master != NULL && strcmp (option_master, "auto") != 0) {
		//FIXME check bdaddr
	}

	libusb_init (NULL);

	/* Find device(s) */
	num_devices = libusb_get_device_list (NULL, &list);
	if (num_devices < 0) {
		g_warning ("libusb_get_device_list failed");
		return 1;
	}

	for (i = 0; i < num_devices; i++) {
		struct libusb_config_descriptor *cfg;
		libusb_device *dev = list[i];
		struct libusb_device_descriptor desc;
		guint8 j;

		if (libusb_get_device_descriptor (dev, &desc) < 0) {
			g_warning ("libusb_get_device_descriptor failed");
			continue;
		}

		/* Here we check for the supported devices */
		if (desc.idVendor != VENDOR || desc.idProduct != PRODUCT)
			continue;

		/* Look for the interface number that interests us */
		for (j = 0; j < desc.bNumConfigurations; j++) {
			struct libusb_config_descriptor *config;
			guint8 k;

			libusb_get_config_descriptor (dev, j, &config);

			for (k = 0; k < config->bNumInterfaces; k++) {
				const struct libusb_interface *itf = &config->interface[k];
				int l;

				for (l = 0; l < itf->num_altsetting ; l++) {
					struct libusb_interface_descriptor alt;

					alt = itf->altsetting[l];
					if (alt.bInterfaceClass == 3) {
						handle_device (dev, cfg, l, &alt);
					}
				}
			}
		}
	}

	return 0;
}
Esempio n. 24
0
void irecv_init()
{
#ifndef WIN32
	libusb_init(&libirecovery_context);
#endif
}
Esempio n. 25
0
/**
 * Wraps a CDB mass storage command in the appropriate gunk to get it down
 * @param handle
 * @param endpoint
 * @param cdb
 * @param cdb_length
 * @param lun
 * @param flags
 * @param expected_rx_size
 * @return
 */
int send_usb_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint_out,
        uint8_t *cdb, uint8_t cdb_length,
        uint8_t lun, uint8_t flags, uint32_t expected_rx_size) {
    DLOG("Sending usb m-s cmd: cdblen:%d, rxsize=%d\n", cdb_length, expected_rx_size);
    dump_CDB_command(cdb, cdb_length);

    static uint32_t tag;
    if (tag == 0) {
        tag = 1;
    }

    int try = 0;
    int ret = 0;
    int real_transferred;
    int i = 0;

    uint8_t c_buf[STLINK_SG_SIZE];
    // tag is allegedly ignored... TODO - verify
    c_buf[i++] = 'U';
    c_buf[i++] = 'S';
    c_buf[i++] = 'B';
    c_buf[i++] = 'C';
    write_uint32(&c_buf[i], tag);
    uint32_t this_tag = tag++;
    write_uint32(&c_buf[i+4], expected_rx_size);
    i+= 8;
    c_buf[i++] = flags;
    c_buf[i++] = lun;

    c_buf[i++] = cdb_length;

    // Now the actual CDB request
    assert(cdb_length <= CDB_SL);
    memcpy(&(c_buf[i]), cdb, cdb_length);

    int sending_length = STLINK_SG_SIZE;

    // send....
    do {
        ret = libusb_bulk_transfer(handle, endpoint_out, c_buf, sending_length,
                &real_transferred, SG_TIMEOUT_MSEC);
        if (ret == LIBUSB_ERROR_PIPE) {
            libusb_clear_halt(handle, endpoint_out);
        }
        try++;
    } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3));
    if (ret != LIBUSB_SUCCESS) {
        WLOG("sending failed: %d\n", ret);
        return -1;
    }
    return this_tag;
}


/**
 * Straight from stm8 stlink code...
 * @param handle
 * @param endpoint_in
 * @param endpoint_out
 */
    static void
get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out)
{
    DLOG("Fetching sense...\n");
    uint8_t cdb[16];
    memset(cdb, 0, sizeof(cdb));
#define REQUEST_SENSE 0x03
#define REQUEST_SENSE_LENGTH 18
    cdb[0] = REQUEST_SENSE;
    cdb[4] = REQUEST_SENSE_LENGTH;
    uint32_t tag = send_usb_mass_storage_command(handle, endpoint_out, cdb, sizeof(cdb), 0,
            LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH);
    if (tag == 0) {
        WLOG("refusing to send request sense with tag 0\n");
        return;
    }
    unsigned char sense[REQUEST_SENSE_LENGTH];
    int transferred;
    int ret;
    int try = 0;
    do {
        ret = libusb_bulk_transfer(handle, endpoint_in, sense, sizeof(sense),
                &transferred, SG_TIMEOUT_MSEC);
        if (ret == LIBUSB_ERROR_PIPE) {
            libusb_clear_halt(handle, endpoint_in);
        }
        try++;
    } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3));
    if (ret != LIBUSB_SUCCESS) {
        WLOG("receiving sense failed: %d\n", ret);
        return;
    }
    if (transferred != sizeof(sense)) {
        WLOG("received unexpected amount of sense: %d != %d\n", transferred, sizeof(sense));
    }
    uint32_t received_tag;
    int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag);
    if (status != 0) {
        WLOG("receiving sense failed with status: %02x\n", status);
        return;
    }
    if (sense[0] != 0x70 && sense[0] != 0x71) {
        WLOG("No sense data\n");
    } else {
        WLOG("Sense KCQ: %02X %02X %02X\n", sense[2] & 0x0f, sense[12], sense[13]);
    }
}

/**
 * Just send a buffer on an endpoint, no questions asked.
 * Handles repeats, and time outs.  Also handles reading status reports and sense
 * @param handle libusb device *
 * @param endpoint_out sends
 * @param endpoint_in used to read status reports back in
 * @param cbuf  what to send
 * @param length how much to send
 * @return number of bytes actually sent, or -1 for failures.
 */
int send_usb_data_only(libusb_device_handle *handle, unsigned char endpoint_out,
        unsigned char endpoint_in, unsigned char *cbuf, unsigned int length) {
    int ret;
    int real_transferred;
    int try = 0;
    do {
        ret = libusb_bulk_transfer(handle, endpoint_out, cbuf, length,
                &real_transferred, SG_TIMEOUT_MSEC);
        if (ret == LIBUSB_ERROR_PIPE) {
            libusb_clear_halt(handle, endpoint_out);
        }
        try++;
    } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3));
    if (ret != LIBUSB_SUCCESS) {
        WLOG("sending failed: %d\n", ret);
        return -1;
    }

    // now, swallow up the status, so that things behave nicely...
    uint32_t received_tag;
    // -ve is for my errors, 0 is good, +ve is libusb sense status bytes
    int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag);
    if (status < 0) {
        WLOG("receiving status failed: %d\n", status);
        return -1;
    }
    if (status != 0) {
        WLOG("receiving status not passed :(: %02x\n", status);
    }
    if (status == 1) {
        get_sense(handle, endpoint_in, endpoint_out);
        return -1;
    }

    return real_transferred;
}


int stlink_q(stlink_t *sl) {
    struct stlink_libsg* sg = sl->backend_data;
    //uint8_t cdb_len = 6;  // FIXME varies!!!
    uint8_t cdb_len = 10;  // FIXME varies!!!
    uint8_t lun = 0;  // always zero...
    uint32_t tag = send_usb_mass_storage_command(sg->usb_handle, sg->ep_req,
            sg->cdb_cmd_blk, cdb_len, lun, LIBUSB_ENDPOINT_IN, sl->q_len);


    // now wait for our response...
    // length copied from stlink-usb...
    int rx_length = sl->q_len;
    int try = 0;
    int real_transferred;
    int ret;
    if (rx_length > 0) {
        do {
            ret = libusb_bulk_transfer(sg->usb_handle, sg->ep_rep, sl->q_buf, rx_length,
                    &real_transferred, SG_TIMEOUT_MSEC);
            if (ret == LIBUSB_ERROR_PIPE) {
                libusb_clear_halt(sg->usb_handle, sg->ep_req);
            }
            try++;
        } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3));

        if (ret != LIBUSB_SUCCESS) {
            WLOG("Receiving failed: %d\n", ret);
            return -1;
        }

        if (real_transferred != rx_length) {
            WLOG("received unexpected amount: %d != %d\n", real_transferred, rx_length);
        }
    }

    uint32_t received_tag;
    // -ve is for my errors, 0 is good, +ve is libusb sense status bytes
    int status = get_usb_mass_storage_status(sg->usb_handle, sg->ep_rep, &received_tag);
    if (status < 0) {
        WLOG("receiving status failed: %d\n", status);
        return -1;
    }
    if (status != 0) {
        WLOG("receiving status not passed :(: %02x\n", status);
    }
    if (status == 1) {
        get_sense(sg->usb_handle, sg->ep_rep, sg->ep_req);
        return -1;
    }
    if (received_tag != tag) {
        WLOG("received tag %d but expected %d\n", received_tag, tag);
        //return -1;
    }
    if (rx_length > 0 && real_transferred != rx_length) {
        return -1;
    }
    return 0;
}

// TODO thinking, cleanup

void stlink_stat(stlink_t *stl, char *txt) {
    if (stl->q_len <= 0)
        return;

    stlink_print_data(stl);

    switch (stl->q_buf[0]) {
    case STLINK_OK:
        DLOG("  %s: ok\n", txt);
        return;
    case STLINK_FALSE:
        DLOG("  %s: false\n", txt);
        return;
    default:
        DLOG("  %s: unknown\n", txt);
    }
}


void _stlink_sg_version(stlink_t *stl) {
    struct stlink_libsg *sl = stl->backend_data;
    clear_cdb(sl);
    sl->cdb_cmd_blk[0] = STLINK_GET_VERSION;
    stl->q_len = 6;
    sl->q_addr = 0;
    stlink_q(stl);
}

// Get stlink mode:
// STLINK_DEV_DFU_MODE || STLINK_DEV_MASS_MODE || STLINK_DEV_DEBUG_MODE
// usb dfu             || usb mass             || jtag or swd

int _stlink_sg_current_mode(stlink_t *stl) {
    struct stlink_libsg *sl = stl->backend_data;
    clear_cdb(sl);
    sl->cdb_cmd_blk[0] = STLINK_GET_CURRENT_MODE;
    stl->q_len = 2;
    sl->q_addr = 0;
    stlink_q(stl);
    return stl->q_buf[0];
}

// Exit the mass mode and enter the swd debug mode.

void _stlink_sg_enter_swd_mode(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER;
    sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_SWD;
    sl->q_len = 0; // >0 -> aboard
    stlink_q(sl);
}

// Exit the mass mode and enter the jtag debug mode.
// (jtag is disabled in the discovery's stlink firmware)

void _stlink_sg_enter_jtag_mode(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    DLOG("\n*** stlink_enter_jtag_mode ***\n");
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER;
    sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_JTAG;
    sl->q_len = 0;
    stlink_q(sl);
}

// XXX kernel driver performs reset, the device temporally disappears
// Suspect this is no longer the case when we have ignore on? RECHECK
void _stlink_sg_exit_dfu_mode(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    DLOG("\n*** stlink_exit_dfu_mode ***\n");
    clear_cdb(sg);
    sg->cdb_cmd_blk[0] = STLINK_DFU_COMMAND;
    sg->cdb_cmd_blk[1] = STLINK_DFU_EXIT;
    sl->q_len = 0; // ??
    stlink_q(sl);
    /*
       [135121.844564] sd 19:0:0:0: [sdb] Unhandled error code
       [135121.844569] sd 19:0:0:0: [sdb] Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK
       [135121.844574] sd 19:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 10 00 00 00 08 00
       [135121.844584] end_request: I/O error, dev sdb, sector 4096
       [135121.844590] Buffer I/O error on device sdb, logical block 512
       [135130.122567] usb 6-1: reset full speed USB device using uhci_hcd and address 7
       [135130.274551] usb 6-1: device firmware changed
       [135130.274618] usb 6-1: USB disconnect, address 7
       [135130.275186] VFS: busy inodes on changed media or resized disk sdb
       [135130.275424] VFS: busy inodes on changed media or resized disk sdb
       [135130.286758] VFS: busy inodes on changed media or resized disk sdb
       [135130.292796] VFS: busy inodes on changed media or resized disk sdb
       [135130.301481] VFS: busy inodes on changed media or resized disk sdb
       [135130.304316] VFS: busy inodes on changed media or resized disk sdb
       [135130.431113] usb 6-1: new full speed USB device using uhci_hcd and address 8
       [135130.629444] usb-storage 6-1:1.0: Quirks match for vid 0483 pid 3744: 102a1
       [135130.629492] scsi20 : usb-storage 6-1:1.0
       [135131.625600] scsi 20:0:0:0: Direct-Access     STM32                          PQ: 0 ANSI: 0
       [135131.627010] sd 20:0:0:0: Attached scsi generic sg2 type 0
       [135131.633603] sd 20:0:0:0: [sdb] 64000 512-byte logical blocks: (32.7 MB/31.2 MiB)
       [135131.633613] sd 20:0:0:0: [sdb] Assuming Write Enabled
       [135131.633620] sd 20:0:0:0: [sdb] Assuming drive cache: write through
       [135131.640584] sd 20:0:0:0: [sdb] Assuming Write Enabled
       [135131.640592] sd 20:0:0:0: [sdb] Assuming drive cache: write through
       [135131.640609]  sdb:
       [135131.652634] sd 20:0:0:0: [sdb] Assuming Write Enabled
       [135131.652639] sd 20:0:0:0: [sdb] Assuming drive cache: write through
       [135131.652645] sd 20:0:0:0: [sdb] Attached SCSI removable disk
       [135131.671536] sd 20:0:0:0: [sdb] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
       [135131.671548] sd 20:0:0:0: [sdb] Sense Key : Illegal Request [current]
       [135131.671553] sd 20:0:0:0: [sdb] Add. Sense: Logical block address out of range
       [135131.671560] sd 20:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 f9 80 00 00 08 00
       [135131.671570] end_request: I/O error, dev sdb, sector 63872
       [135131.671575] Buffer I/O error on device sdb, logical block 7984
       [135131.678527] sd 20:0:0:0: [sdb] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
       [135131.678532] sd 20:0:0:0: [sdb] Sense Key : Illegal Request [current]
       [135131.678537] sd 20:0:0:0: [sdb] Add. Sense: Logical block address out of range
       [135131.678542] sd 20:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 f9 80 00 00 08 00
       [135131.678551] end_request: I/O error, dev sdb, sector 63872
       ...
       [135131.853565] end_request: I/O error, dev sdb, sector 4096
       */
}

void _stlink_sg_core_id(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_READCOREID;
    sl->q_len = 4;
    sg->q_addr = 0;
    stlink_q(sl);
    sl->core_id = read_uint32(sl->q_buf, 0);
}

// Arm-core reset -> halted state.

void _stlink_sg_reset(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_RESETSYS;
    sl->q_len = 2;
    sg->q_addr = 0;
    stlink_q(sl);
    stlink_stat(sl, "core reset");
}

// Arm-core reset -> halted state.

void _stlink_sg_jtag_reset(stlink_t *sl, int value) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_JTAG_DRIVE_NRST;
    sg->cdb_cmd_blk[2] = (value)?0:1;
    sl->q_len = 3;
    sg->q_addr = 2;
    stlink_q(sl);
    stlink_stat(sl, "core reset");
}

// Arm-core status: halted or running.

void _stlink_sg_status(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_GETSTATUS;
    sl->q_len = 2;
    sg->q_addr = 0;
    stlink_q(sl);
}

// Force the core into the debug mode -> halted state.

void _stlink_sg_force_debug(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_FORCEDEBUG;
    sl->q_len = 2;
    sg->q_addr = 0;
    stlink_q(sl);
    stlink_stat(sl, "force debug");
}

// Read all arm-core registers.

void _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) {
    struct stlink_libsg *sg = sl->backend_data;

    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_READALLREGS;
    sl->q_len = 84;
    sg->q_addr = 0;
    stlink_q(sl);
    stlink_print_data(sl);

    // TODO - most of this should be re-extracted up....

    // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71   | 72-75      | 76-79 | 80-83
    // r0  | r1  | ... | r15   | xpsr  | main_sp | process_sp | rw    | rw2
    for (int i = 0; i < 16; i++) {
        regp->r[i] = read_uint32(sl->q_buf, 4 * i);
        if (sl->verbose > 1)
            DLOG("r%2d = 0x%08x\n", i, regp->r[i]);
    }
    regp->xpsr = read_uint32(sl->q_buf, 64);
    regp->main_sp = read_uint32(sl->q_buf, 68);
    regp->process_sp = read_uint32(sl->q_buf, 72);
    regp->rw = read_uint32(sl->q_buf, 76);
    regp->rw2 = read_uint32(sl->q_buf, 80);
    if (sl->verbose < 2)
        return;

    DLOG("xpsr       = 0x%08x\n", regp->xpsr);
    DLOG("main_sp    = 0x%08x\n", regp->main_sp);
    DLOG("process_sp = 0x%08x\n", regp->process_sp);
    DLOG("rw         = 0x%08x\n", regp->rw);
    DLOG("rw2        = 0x%08x\n", regp->rw2);
}

// Read an arm-core register, the index must be in the range 0..20.
//  0  |  1  | ... |  15   |  16   |   17    |   18       |  19   |  20
// r0  | r1  | ... | r15   | xpsr  | main_sp | process_sp | rw    | rw2

void _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_READREG;
    sg->cdb_cmd_blk[2] = r_idx;
    sl->q_len = 4;
    sg->q_addr = 0;
    stlink_q(sl);
    //  0  |  1  | ... |  15   |  16   |   17    |   18       |  19   |  20
    // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71   | 72-75      | 76-79 | 80-83
    // r0  | r1  | ... | r15   | xpsr  | main_sp | process_sp | rw    | rw2
    stlink_print_data(sl);

    uint32_t r = read_uint32(sl->q_buf, 0);
    DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r);

    switch (r_idx) {
    case 16:
        regp->xpsr = r;
        break;
    case 17:
        regp->main_sp = r;
        break;
    case 18:
        regp->process_sp = r;
        break;
    case 19:
        regp->rw = r; //XXX ?(primask, basemask etc.)
        break;
    case 20:
        regp->rw2 = r; //XXX ?(primask, basemask etc.)
        break;
    default:
        regp->r[r_idx] = r;
    }
}

// Write an arm-core register. Index:
//  0  |  1  | ... |  15   |  16   |   17    |   18       |  19   |  20
// r0  | r1  | ... | r15   | xpsr  | main_sp | process_sp | rw    | rw2

void _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEREG;
    //   2: reg index
    // 3-6: reg content
    sg->cdb_cmd_blk[2] = idx;
    write_uint32(sg->cdb_cmd_blk + 3, reg);
    sl->q_len = 2;
    sg->q_addr = 0;
    stlink_q(sl);
    stlink_stat(sl, "write reg");
}

// Write a register of the debug module of the core.
// XXX ?(atomic writes)
// TODO test

void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) {
    struct stlink_libsg *sg = sl->backend_data;
    DLOG("\n*** stlink_write_dreg ***\n");
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEDEBUGREG;
    // 2-5: address of reg of the debug module
    // 6-9: reg content
    write_uint32(sg->cdb_cmd_blk + 2, addr);
    write_uint32(sg->cdb_cmd_blk + 6, reg);
    sl->q_len = 2;
    sg->q_addr = addr;
    stlink_q(sl);
    stlink_stat(sl, "write debug reg");
}

// Force the core exit the debug mode.

void _stlink_sg_run(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE;
    sl->q_len = 2;
    sg->q_addr = 0;
    stlink_q(sl);
    stlink_stat(sl, "run core");
}

// Step the arm-core.

void _stlink_sg_step(stlink_t *sl) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_STEPCORE;
    sl->q_len = 2;
    sg->q_addr = 0;
    stlink_q(sl);
    stlink_stat(sl, "step core");
}

// TODO test
// see Cortex-M3 Technical Reference Manual
// TODO make delegate!
void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) {
    DLOG("\n*** stlink_set_hw_bp ***\n");
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_SETFP;
    // 2:The number of the flash patch used to set the breakpoint
    // 3-6: Address of the breakpoint (LSB)
    // 7: FP_ALL (0x02) / FP_UPPER (0x01) / FP_LOWER (0x00)
    sl->q_buf[2] = fp_nr;
    write_uint32(sl->q_buf, addr);
    sl->q_buf[7] = fp;

    sl->q_len = 2;
    stlink_q(sl);
    stlink_stat(sl, "set flash breakpoint");
}

// TODO test

// TODO make delegate!
void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) {
    struct stlink_libsg *sg = sl->backend_data;
    DLOG("\n*** stlink_clr_hw_bp ***\n");
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_CLEARFP;
    sg->cdb_cmd_blk[2] = fp_nr;

    sl->q_len = 2;
    stlink_q(sl);
    stlink_stat(sl, "clear flash breakpoint");
}

// Read a "len" bytes to the sl->q_buf from the memory, max 6kB (6144 bytes)

void _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_READMEM_32BIT;
    // 2-5: addr
    // 6-7: len
    write_uint32(sg->cdb_cmd_blk + 2, addr);
    write_uint16(sg->cdb_cmd_blk + 6, len);

    // data_in 0-0x40-len
    // !!! len _and_ q_len must be max 6k,
    //     i.e. >1024 * 6 = 6144 -> aboard)
    // !!! if len < q_len: 64*k, 1024*n, n=1..5  -> aboard
    //     (broken residue issue)
    sl->q_len = len;
    sg->q_addr = addr;
    stlink_q(sl);
    stlink_print_data(sl);
}

// Write a "len" bytes from the sl->q_buf to the memory, max 64 Bytes.

void _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_8BIT;
    // 2-5: addr
    // 6-7: len (>0x40 (64) -> aboard)
    write_uint32(sg->cdb_cmd_blk + 2, addr);
    write_uint16(sg->cdb_cmd_blk + 6, len);

    // this sends the command...
    send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0);
    // This sends the data...
    send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len);
    stlink_print_data(sl);
}

// Write a "len" bytes from the sl->q_buf to the memory, max Q_BUF_LEN bytes.

void _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_32BIT;
    // 2-5: addr
    // 6-7: len "unlimited"
    write_uint32(sg->cdb_cmd_blk + 2, addr);
    write_uint16(sg->cdb_cmd_blk + 6, len);

    // this sends the command...
    send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0);
    // This sends the data...
    send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len);

    stlink_print_data(sl);
}

// Write one DWORD data to memory

void _stlink_sg_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_JTAG_WRITEDEBUG_32BIT;
    // 2-5: addr
    write_uint32(sg->cdb_cmd_blk + 2, addr);
    write_uint32(sg->cdb_cmd_blk + 6, data);
    sl->q_len = 2;
    stlink_q(sl);

}

// Read one DWORD data from memory

uint32_t _stlink_sg_read_debug32(stlink_t *sl, uint32_t addr) {
    struct stlink_libsg *sg = sl->backend_data;
    clear_cdb(sg);
    sg->cdb_cmd_blk[1] = STLINK_JTAG_READDEBUG_32BIT;
    // 2-5: addr
    write_uint32(sg->cdb_cmd_blk + 2, addr);
    sl->q_len = 8;
    stlink_q(sl);

    return read_uint32(sl->q_buf, 4);
}

// Exit the jtag or swd mode and enter the mass mode.

void _stlink_sg_exit_debug_mode(stlink_t *stl) {

    if (stl) {
        struct stlink_libsg* sl = stl->backend_data;
        clear_cdb(sl);
        sl->cdb_cmd_blk[1] = STLINK_DEBUG_EXIT;
        stl->q_len = 0; // >0 -> aboard
        stlink_q(stl);
    }
}


// 1) open a sg device, switch the stlink from dfu to mass mode
// 2) wait 5s until the kernel driver stops reseting the broken device
// 3) reopen the device
// 4) the device driver is now ready for a switch to jtag/swd mode
// TODO thinking, better error handling, wait until the kernel driver stops reseting the plugged-in device

stlink_backend_t _stlink_sg_backend = {
    _stlink_sg_close,
    _stlink_sg_exit_debug_mode,
    _stlink_sg_enter_swd_mode,
    _stlink_sg_enter_jtag_mode,
    _stlink_sg_exit_dfu_mode,
    _stlink_sg_core_id,
    _stlink_sg_reset,
    _stlink_sg_jtag_reset,
    _stlink_sg_run,
    _stlink_sg_status,
    _stlink_sg_version,
    _stlink_sg_read_debug32,
    _stlink_sg_read_mem32,
    _stlink_sg_write_debug32,
    _stlink_sg_write_mem32,
    _stlink_sg_write_mem8,
    _stlink_sg_read_all_regs,
    _stlink_sg_read_reg,
    NULL,                   /* read_all_unsupported_regs */
    NULL,                   /* read_unsupported_regs */
    NULL,                   /* write_unsupported_regs */
    _stlink_sg_write_reg,
    _stlink_sg_step,
    _stlink_sg_current_mode,
    _stlink_sg_force_debug,
    NULL
};

static stlink_t* stlink_open(const int verbose) {

    stlink_t *sl = malloc(sizeof (stlink_t));
    memset(sl, 0, sizeof(stlink_t));
    struct stlink_libsg *slsg = malloc(sizeof (struct stlink_libsg));
    if (sl == NULL || slsg == NULL) {
        WLOG("Couldn't malloc stlink and stlink_sg structures out of memory!\n");
        return NULL;
    }

    if (libusb_init(&(slsg->libusb_ctx))) {
        WLOG("failed to init libusb context, wrong version of libraries?\n");
        free(sl);
        free(slsg);
        return NULL;
    }

    libusb_set_debug(slsg->libusb_ctx, 3);

    slsg->usb_handle = libusb_open_device_with_vid_pid(slsg->libusb_ctx, USB_ST_VID, USB_STLINK_PID);
    if (slsg->usb_handle == NULL) {
        WLOG("Failed to find an stlink v1 by VID:PID\n");
        libusb_close(slsg->usb_handle);
        libusb_exit(slsg->libusb_ctx);
        free(sl);
        free(slsg);
        return NULL;
    }

    // TODO
    // Could read the interface config descriptor, and assert lots of the assumptions

    // assumption: numInterfaces is always 1...
    if (libusb_kernel_driver_active(slsg->usb_handle, 0) == 1) {
        int r = libusb_detach_kernel_driver(slsg->usb_handle, 0);
        if (r < 0) {
            WLOG("libusb_detach_kernel_driver(() error %s\n", strerror(-r));
            libusb_close(slsg->usb_handle);
            libusb_exit(slsg->libusb_ctx);
            free(sl);
            free(slsg);
            return NULL;
        }
        DLOG("Kernel driver was successfully detached\n");
    }

    int config;
    if (libusb_get_configuration(slsg->usb_handle, &config)) {
        /* this may fail for a previous configured device */
        WLOG("libusb_get_configuration()\n");
        libusb_close(slsg->usb_handle);
        libusb_exit(slsg->libusb_ctx);
        free(sl);
        free(slsg);
        return NULL;

    }

    // assumption: bConfigurationValue is always 1
    if (config != 1) {
        WLOG("Your stlink got into a real weird configuration, trying to fix it!\n");
        DLOG("setting new configuration (%d -> 1)\n", config);
        if (libusb_set_configuration(slsg->usb_handle, 1)) {
            /* this may fail for a previous configured device */
            WLOG("libusb_set_configuration() failed\n");
            libusb_close(slsg->usb_handle);
            libusb_exit(slsg->libusb_ctx);
            free(sl);
            free(slsg);
            return NULL;
        }
    }

    if (libusb_claim_interface(slsg->usb_handle, 0)) {
        WLOG("libusb_claim_interface() failed\n");
        libusb_close(slsg->usb_handle);
        libusb_exit(slsg->libusb_ctx);
        free(sl);
        free(slsg);
        return NULL;
    }

    // assumption: endpoint config is fixed mang. really.
    slsg->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN;
    slsg->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT;

    DLOG("Successfully opened stlinkv1 by libusb :)\n");

    sl->verbose = verbose;
    sl->backend_data = slsg;
    sl->backend = &_stlink_sg_backend;

    sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
    slsg->q_addr = 0;

    return sl;
}
Esempio n. 26
0
int main(int argc, char **argv) {
    libusb_context *c;
    libusb_device_handle *h;
    int offset = 0, size = 0;
    char action;

    NEXT; if (!argc) usage();

    action = **argv; NEXT;

    switch(action) {
    case 'b':
        if (argc) usage();
        break;
    case 'e': case 'r': case 'w':
        if (argc!=2) usage();
        offset = strtoul(argv[0], NULL, 0);
        size   = strtoul(argv[1], NULL, 0);
        break;
    case 'v': case 'V':
        printf("rkflashtool version %d.%d\n",
               RKFLASHTOOL_VER_MAJOR, RKFLASHTOOL_VER_MINOR);
        exit(0);
        break;
    default:
        usage();
    }

    if (libusb_init(&c)) fatal("cannot init libusb\n");

    libusb_set_debug(c, 3);

    if (!(h = libusb_open_device_with_vid_pid(c, 0x2207, 0x290a)))
        if (!(h = libusb_open_device_with_vid_pid(c, 0x2207, 0x281a)))
        if (!(h = libusb_open_device_with_vid_pid(c, 0x2207, 0x300a)))
        if (!(h = libusb_open_device_with_vid_pid(c, 0x2207, 0x310b)))
            fatal("cannot open device\n");

    if (libusb_kernel_driver_active(h, 0) == 1) {
        info("kernel driver active\n");
        if (!libusb_detach_kernel_driver(h, 0))
            info("driver detached\n");
    }

    if (libusb_claim_interface(h, 0)<0) fatal("cannot claim interface\n");
    info("interface claimed\n");

    send_cmd(h, 2, 0x80, 0x00060000, 0x00000000, 0x00);        /* INIT */
    recv_res(h, 1);
    usleep(20*1000);

    switch(action) {
    case 'b':
        info("rebooting device...\n");
        send_cmd(h, 2, 0x00, 0x0006ff00, 0x00000000, 0x00);
        recv_res(h, 1);
        break;
    case 'r':
        while (size>0) {
            if (offset % RKFT_DISPLAY == 0)
                info("reading flash memory at offset 0x%08x\r", offset);

            send_cmd(h, 2, 0x80, 0x000a1400, offset, RKFT_OFF_INCR);
            recv_buf(h, 1, RKFT_BLOCKSIZE);
            recv_res(h, 1);

            /* check for write() errors to catch disk-full, no-perms, etc. */
            if (write(1, buf, RKFT_BLOCKSIZE) < 0)
                fatal("error writing buffer to stdout: %s\n", strerror(errno));
            offset += RKFT_OFF_INCR;
            size   -= RKFT_OFF_INCR;
        }
        fprintf(stderr, "\n");
        break;
    case 'w':
        while (size>0) {
            if (offset % RKFT_DISPLAY == 0)
                info("writing flash memory at offset 0x%08x\r", offset);

            memset(buf, 0, RKFT_BLOCKSIZE);
            /* we ignore here read() errors and pad up to given size */
            if (read(0, buf, RKFT_BLOCKSIZE) < 0) {};

            send_cmd(h, 2, 0x80, 0x000a1500, offset, RKFT_OFF_INCR);
            send_buf(h, 2, RKFT_BLOCKSIZE);
            recv_res(h, 1);

            offset += RKFT_OFF_INCR;
            size   -= RKFT_OFF_INCR;
        }
        fprintf(stderr, "\n");
        break;
    case 'e':
        memset(buf, RKFT_FILLBYTE, RKFT_BLOCKSIZE);
        while (size>0) {
            if (offset % RKFT_DISPLAY == 0)
                info("erasing flash memory at offset 0x%08x\r", offset);

            send_cmd(h, 2, 0x80, 0x000a1500, offset, RKFT_OFF_INCR);
            send_buf(h, 2, RKFT_BLOCKSIZE);
            recv_res(h, 1);

            offset += RKFT_OFF_INCR;
            size   -= RKFT_OFF_INCR;
        }
        fprintf(stderr, "\n");
        break;
    default:
        break;
    }

    libusb_release_interface(h, 0);
    libusb_close(h);
    libusb_exit(c);
    return 0;
}
Esempio n. 27
0
int main(void)
{
	struct sigaction sigact;
	int r = 1;

	r = libusb_init(NULL);
	if (r < 0) {
		fprintf(stderr, "failed to initialise libusb\n");
		exit(1);
	}

	r = find_dpfp_device();
	if (r < 0) {
		fprintf(stderr, "Could not find/open device\n");
		goto out;
	}

	r = libusb_claim_interface(devh, 0);
	if (r < 0) {
		fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r));
		goto out;
	}
	printf("claimed interface\n");

	r = print_f0_data();
	if (r < 0)
		goto out_release;

	r = do_init();
	if (r < 0)
		goto out_deinit;

	/* async from here onwards */

	sigact.sa_handler = sighandler;
	sigemptyset(&sigact.sa_mask);
	sigact.sa_flags = 0;
	sigaction(SIGINT, &sigact, NULL);
	sigaction(SIGTERM, &sigact, NULL);
	sigaction(SIGQUIT, &sigact, NULL);

	r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL);
	if (r)
		goto out_deinit;

	r = alloc_transfers();
	if (r < 0) {
		request_exit(1);
		pthread_join(poll_thread, NULL);
		goto out_deinit;
	}

	r = init_capture();
	if (r < 0) {
		request_exit(1);
		pthread_join(poll_thread, NULL);
		goto out_deinit;
	}

	while (!do_exit) {
		pthread_mutex_lock(&exit_cond_lock);
		pthread_cond_wait(&exit_cond, &exit_cond_lock);
		pthread_mutex_unlock(&exit_cond_lock);
	}

	printf("shutting down...\n");
	pthread_join(poll_thread, NULL);

	r = libusb_cancel_transfer(irq_transfer);
	if (r < 0) {
		request_exit(1);
		goto out_deinit;
	}

	r = libusb_cancel_transfer(img_transfer);
	if (r < 0) {
		request_exit(1);
		goto out_deinit;
	}

	while (img_transfer || irq_transfer)
		if (libusb_handle_events(NULL) < 0)
			break;

	if (do_exit == 1)
		r = 0;
	else
		r = 1;

out_deinit:
	libusb_free_transfer(img_transfer);
	libusb_free_transfer(irq_transfer);
	set_mode(0);
	set_hwstat(0x80);
out_release:
	libusb_release_interface(devh, 0);
out:
	libusb_close(devh);
	libusb_exit(NULL);
	return r >= 0 ? r : -r;
}
Esempio n. 28
0
struct launchpad* lp_register()
{
    struct launchpad *lp;
    
    //build the struct
    lp = malloc(sizeof(struct launchpad));
    if (lp == NULL) {
	fprintf(stderr,"Unable to allocate memory\n");
	return NULL;
    }
    
    //initialize usb
    if(libusb_init(NULL)!=0){
	fprintf(stderr,"Unable to initialize usb\n");
	return NULL;
    } else {
        printf("usb initialized\n");
    }
    
    //find the device
    lp->device = libusb_open_device_with_vid_pid(NULL, ID_VENDOR, ID_PRODUCT);
    if (lp->device == NULL) {
	fprintf(stderr,"Unable to find the launchpad\n");
 	return NULL;
    } else {
        printf("launchpad found\n");
    }
    
    //claim the device
    if(libusb_claim_interface(lp->device, 0) != 0) {
	fprintf(stderr,"Unable to claim the launchpad\n");
	return NULL;
    } else {
	printf("launchpad claimed\n");
    }
  
    //allocate input buffer
    lp->rdata = malloc(sizeof(unsigned char)*MAX_PACKET_SIZE);
    
    if (lp->rdata == NULL) {
	fprintf(stderr,"could not allocate input buffer\n");
	return NULL;
    }
    
    //allocate output buffer
    lp->tdata = malloc(sizeof(unsigned char)*MAX_PACKET_SIZE);
  
    if (lp->tdata == NULL) {
	fprintf(stderr,"could not allocate output buffer\n");
	return NULL;
    }
        
    // initialize the protocol's state
    lp->event[0] = NOTE;
    lp->parse_at = 0;
    lp->received = 0;

    // reset launchpad
    lp_reset(lp);
    
    return lp;
}
Esempio n. 29
0
  int iusb_init (byte ep_in_addr, byte ep_out_addr) {
    logd ("ep_in_addr: %d  ep_out_addr: %d", ep_in_addr, ep_out_addr);

    iusb_ep_in  = -1;
    iusb_ep_out = -1;
    iusb_best_device = NULL;
    iusb_best_vendor = 0;

    int usb_err = libusb_init (NULL);
    if (usb_err < 0) {
      loge ("Error libusb_init usb_err: %d (%s)", usb_err, iusb_error_get (usb_err));
      return (-1);
    }
    logd ("OK libusb_init usb_err: %d", usb_err);

    libusb_set_debug (NULL, LIBUSB_LOG_LEVEL_WARNING);    // DEBUG);//
    logd ("Done libusb_set_debug");

    libusb_device ** list;
    usb_err = libusb_get_device_list (NULL, & list);                // Get list of USB devices
    if (usb_err < 0) {
      loge ("Error libusb_get_device_list cnt: %d", usb_err, iusb_error_get (usb_err));
      return (-1);
    }
    ssize_t cnt = usb_err;
    logd ("Done libusb_get_device_list cnt: %d", cnt);
    int idx = 0;
    int iusb_best_vendor_priority = 0;

    libusb_device * device;
    for (idx = 0; idx < cnt; idx ++) {                                  // For all USB devices...
      device = list [idx];
      int vendor = iusb_vendor_get (device);
      //int product = product_get (device);
      logd ("iusb_vendor_get vendor: 0x%04x  device: %p", vendor, device);
      if (vendor) {
        int vendor_priority = iusb_vendor_priority_get (vendor);
        //if (iusb_best_vendor_priority <  vendor_priority) {  // For first
        if (iusb_best_vendor_priority <= vendor_priority) {  // For last
          iusb_best_vendor_priority = vendor_priority;
          iusb_best_vendor = vendor;
          iusb_best_device = device;
          strncpy (iusb_best_man, iusb_curr_man, sizeof (iusb_best_man));
          strncpy (iusb_best_pro, iusb_curr_pro, sizeof (iusb_best_pro));
        }
      }
    }
    if (iusb_best_vendor == 0 || iusb_best_device == NULL) {                                             // If no vendor...
      loge ("Error device not found iusb_best_vendor: 0x%04x  iusb_best_device: %p", iusb_best_vendor, iusb_best_device);
      libusb_free_device_list (list, 1);                                // Free device list now that we are finished with it
      return (-1);
    }
    logd ("Device found iusb_best_vendor: 0x%04x  iusb_best_device: 0x%04x  iusb_best_man: \"%s\"  iusb_best_pro: \"%s\"", iusb_best_vendor, iusb_best_device, iusb_best_man, iusb_best_pro);

    //usb_perms_set ();                                                   // Setup USB permissions, where needed


    if (file_get ("/sdcard/suc")) {    // Set Permission w/ SU:
      int ret = system ("su -c chmod -R 777 /dev/bus 1>/dev/null 2>/dev/null"); // !! Binaries like ssd that write to stdout cause C system() to crash !
      logd ("iusb_usb_init system() ret: %d", ret);
    }


    usb_err = libusb_open (iusb_best_device, & iusb_dev_hndl);
    logd ("libusb_open usb_err: %d (%s)  iusb_dev_hndl: %p  list: %p", usb_err, iusb_error_get (usb_err), iusb_dev_hndl, list);

    libusb_free_device_list (list, 1);                                  // Free device list now that we are finished with it

    if (usb_err != 0) {
      loge ("Error libusb_open usb_err: %d (%s)", usb_err, iusb_error_get (usb_err));
      return (-1);
    }
    logd ("Done libusb_open iusb_dev_hndl: %p", iusb_dev_hndl);

/*
    usb_err = libusb_set_auto_detach_kernel_driver (iusb_dev_hndl, 1);
    if (usb_err)
      loge ("Done libusb_set_auto_detach_kernel_driver usb_err: %d (%s)", usb_err, iusb_error_get (usb_err));
    else
      logd ("Done libusb_set_auto_detach_kernel_driver usb_err: %d (%s)", usb_err, iusb_error_get (usb_err));
//*/
    usb_err = libusb_claim_interface (iusb_dev_hndl, 0);
    if (usb_err)
      loge ("Error libusb_claim_interface usb_err: %d (%s)", usb_err, iusb_error_get (usb_err));
    else
      logd ("OK libusb_claim_interface usb_err: %d (%s)", usb_err, iusb_error_get (usb_err));

    struct libusb_config_descriptor * config = NULL;
    usb_err = libusb_get_config_descriptor (iusb_best_device, 0, & config);
    if (usb_err != 0) {
      logd ("Expected Error libusb_get_config_descriptor usb_err: %d (%s)", usb_err, iusb_error_get (usb_err));    // !! ???? Normal error now ???
      //return (-1);
      iusb_ep_in  = ep_in_addr; //129;                                  // Set  input endpoint
      iusb_ep_out = ep_out_addr;//  2;                                  // Set output endpoint
      return (0);
    }

    int num_int = config->bNumInterfaces;                               // Get number of interfaces
    logd ("Done get_config_descriptor config: %p  num_int: %d", config, num_int);

    const struct libusb_interface            * inter;
    const struct libusb_interface_descriptor * interdesc;
    const struct libusb_endpoint_descriptor  * epdesc;

    for (idx = 0; idx < num_int; idx ++) {                              // For all interfaces...
      inter = & config->interface [idx];
      int num_altsetting = inter->num_altsetting;
      logd ("num_altsetting: %d", num_altsetting);
      int j = 0;
      for (j = 0; j < inter->num_altsetting; j ++) {                    // For all alternate settings...
        interdesc = & inter->altsetting [j];
        int num_int = interdesc->bInterfaceNumber;
        logd ("num_int: %d", num_int);
        int num_eps = interdesc->bNumEndpoints;
        logd ("num_eps: %d", num_eps);
        int k = 0;
        for (k = 0; k < num_eps; k ++) {                                // For all endpoints...
	        epdesc = & interdesc->endpoint [k];
          if (epdesc->bDescriptorType == LIBUSB_DT_ENDPOINT) {          // 5
            if ((epdesc->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK) {
              int ep_add = epdesc->bEndpointAddress;
              if (ep_add & LIBUSB_ENDPOINT_DIR_MASK) {
                if (iusb_ep_in < 0) {
                  iusb_ep_in = ep_add;                                   // Set input endpoint
                  logd ("iusb_ep_in: 0x%02x", iusb_ep_in);
                }
              }
              else {
                if (iusb_ep_out < 0) {
                  iusb_ep_out = ep_add;                                  // Set output endpoint
                  logd ("iusb_ep_out: 0x%02x", iusb_ep_out);
                }
              }
              if (iusb_ep_in > 0 && iusb_ep_out > 0) {                    // If we have both endpoints now...
                libusb_free_config_descriptor (config);

                if ((ep_in_addr != -1 || ep_out_addr != -1) && (iusb_ep_in != ep_in_addr || iusb_ep_out != ep_out_addr)) {
                  loge ("MISMATCH Done endpoint search iusb_ep_in: 0x%02x  iusb_ep_out: 0x%02x", iusb_ep_in, iusb_ep_out);    // Favor libusb over passed in
                }
                else
                  logd ("Match Done endpoint search iusb_ep_in: 0x%02x  iusb_ep_out: 0x%02x", iusb_ep_in, iusb_ep_out);

                return (0);
              }
            }
          }
        }
      }
    }
                                                                        // Else if DON'T have both endpoints...
    loge ("Error in and/or out endpoints unknown iusb_ep_in: 0x%02x  iusb_ep_out: 0x%02x", iusb_ep_in, iusb_ep_out);
    libusb_free_config_descriptor (config);

    if (iusb_ep_in == -1)
      iusb_ep_in  = ep_in_addr; //129;                                  // Set  input endpoint
    if (iusb_ep_out == -1)
      iusb_ep_out = ep_out_addr;//  2;                                  // Set output endpoint

    if (iusb_ep_in == -1 || iusb_ep_out == -1)
      return (-1);

    loge ("!!!!! FIXED EP's !!!!!");
    return (0);
  }
Esempio n. 30
0
/** @brief detect devices based on usb pid / vid.
 *  @return list with usb VID / PID values.
 */
QMap<uint32_t, QString> System::listUsbDevices(void)
{
    QMap<uint32_t, QString> usbids;
    // usb pid detection
    LOG_INFO() << "Searching for USB devices";
#if defined(Q_OS_LINUX)
#if defined(LIBUSB1)
    libusb_device **devs;
    if(libusb_init(NULL) != 0) {
        LOG_ERROR() << "Initializing libusb-1 failed.";
        return usbids;
    }

    if(libusb_get_device_list(NULL, &devs) < 1) {
        LOG_ERROR() << "Error getting device list.";
        return usbids;
    }
    libusb_device *dev;
    int i = 0;
    while((dev = devs[i++]) != NULL) {
        QString name;
        unsigned char buf[256];
        uint32_t id;
        struct libusb_device_descriptor descriptor;
        if(libusb_get_device_descriptor(dev, &descriptor) == 0) {
            id = descriptor.idVendor << 16 | descriptor.idProduct;

            libusb_device_handle *dh;
            if(libusb_open(dev, &dh) == 0) {
                libusb_get_string_descriptor_ascii(dh, descriptor.iManufacturer, buf, 256);
                name += QString::fromLatin1((char*)buf) + " ";
                libusb_get_string_descriptor_ascii(dh, descriptor.iProduct, buf, 256);
                name += QString::fromLatin1((char*)buf);
                libusb_close(dh);
            }
            if(name.isEmpty())
                name = tr("(no description available)");
            if(id) {
                usbids.insertMulti(id, name);
                LOG_INFO("USB: 0x%08x, %s", id, name.toLocal8Bit().data());
            }
        }
    }

    libusb_free_device_list(devs, 1);
    libusb_exit(NULL);
#else
    usb_init();
    usb_find_busses();
    usb_find_devices();
    struct usb_bus *b;
    b = usb_busses;

    while(b) {
        if(b->devices) {
            struct usb_device *u;
            u = b->devices;
            while(u) {
                uint32_t id;
                id = u->descriptor.idVendor << 16 | u->descriptor.idProduct;
                // get identification strings
                usb_dev_handle *dev;
                QString name;
                char string[256];
                int res;
                dev = usb_open(u);
                if(dev) {
                    if(u->descriptor.iManufacturer) {
                        res = usb_get_string_simple(dev, u->descriptor.iManufacturer,
                                                    string, sizeof(string));
                        if(res > 0)
                            name += QString::fromLatin1(string) + " ";
                    }
                    if(u->descriptor.iProduct) {
                        res = usb_get_string_simple(dev, u->descriptor.iProduct,
                                                    string, sizeof(string));
                        if(res > 0)
                            name += QString::fromLatin1(string);
                    }
                    usb_close(dev);
                }
                if(name.isEmpty()) name = tr("(no description available)");

                if(id) {
                    usbids.insertMulti(id, name);
                    LOG_INFO() << "USB:" << QString("0x%1").arg(id, 8, 16) << name;
                }
                u = u->next;
            }
        }
        b = b->next;
    }
#endif
#endif

#if defined(Q_OS_MACX)
    kern_return_t result = KERN_FAILURE;
    CFMutableDictionaryRef usb_matching_dictionary;
    io_iterator_t usb_iterator = IO_OBJECT_NULL;
    usb_matching_dictionary = IOServiceMatching(kIOUSBDeviceClassName);
    result = IOServiceGetMatchingServices(kIOMasterPortDefault, usb_matching_dictionary,
                                          &usb_iterator);
    if(result) {
        LOG_ERROR() << "USB: IOKit: Could not get matching services.";
        return usbids;
    }

    io_object_t usbCurrentObj;
    while((usbCurrentObj = IOIteratorNext(usb_iterator))) {
        uint32_t id;
        QString name;
        /* get vendor ID */
        CFTypeRef vidref = NULL;
        int vid = 0;
        vidref = IORegistryEntryCreateCFProperty(usbCurrentObj, CFSTR("idVendor"),
                                kCFAllocatorDefault, 0);
        CFNumberGetValue((CFNumberRef)vidref, kCFNumberIntType, &vid);
        CFRelease(vidref);

        /* get product ID */
        CFTypeRef pidref = NULL;
        int pid = 0;
        pidref = IORegistryEntryCreateCFProperty(usbCurrentObj, CFSTR("idProduct"),
                                kCFAllocatorDefault, 0);
        CFNumberGetValue((CFNumberRef)pidref, kCFNumberIntType, &pid);
        CFRelease(pidref);
        id = vid << 16 | pid;

        /* get product vendor */
        char vendor_buf[256];
        CFIndex vendor_buflen = 256;
        CFTypeRef vendor_name_ref = NULL;

        vendor_name_ref = IORegistryEntrySearchCFProperty(usbCurrentObj,
                                 kIOServicePlane, CFSTR("USB Vendor Name"),
                                 kCFAllocatorDefault, 0);
        if(vendor_name_ref != NULL) {
            CFStringGetCString((CFStringRef)vendor_name_ref, vendor_buf, vendor_buflen,
                               kCFStringEncodingUTF8);
            name += QString::fromUtf8(vendor_buf) + " ";
            CFRelease(vendor_name_ref);
        }
        else {
            name += QObject::tr("(unknown vendor name) ");
        }

        /* get product name */
        char product_buf[256];
        CFIndex product_buflen = 256;
        CFTypeRef product_name_ref = NULL;

        product_name_ref = IORegistryEntrySearchCFProperty(usbCurrentObj,
                                kIOServicePlane, CFSTR("USB Product Name"),
                                kCFAllocatorDefault, 0);
        if(product_name_ref != NULL) {
            CFStringGetCString((CFStringRef)product_name_ref, product_buf, product_buflen,
                               kCFStringEncodingUTF8);
            name += QString::fromUtf8(product_buf);
            CFRelease(product_name_ref);
        }
        else {
            name += QObject::tr("(unknown product name)");
        }

        if(id) {
            usbids.insertMulti(id, name);
            LOG_INFO() << "USB:" << QString("0x%1").arg(id, 8, 16) << name;
        }

    }
    IOObjectRelease(usb_iterator);
#endif

#if defined(Q_OS_WIN32)
    HDEVINFO deviceInfo;
    SP_DEVINFO_DATA infoData;
    DWORD i;

    // Iterate over all devices
    // by doing it this way it's unneccessary to use GUIDs which might be not
    // present in current MinGW. It also seemed to be more reliably than using
    // a GUID.
    // See KB259695 for an example.
    deviceInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);

    infoData.cbSize = sizeof(SP_DEVINFO_DATA);

    for(i = 0; SetupDiEnumDeviceInfo(deviceInfo, i, &infoData); i++) {
        DWORD data;
        LPTSTR buffer = NULL;
        DWORD buffersize = 0;
        QString description;

        // get device desriptor first
        // for some reason not doing so results in bad things (tm)
        while(!SetupDiGetDeviceRegistryProperty(deviceInfo, &infoData,
            SPDRP_DEVICEDESC, &data, (PBYTE)buffer, buffersize, &buffersize)) {
            if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                if(buffer) free(buffer);
                // double buffer size to avoid problems as per KB888609
                buffer = (LPTSTR)malloc(buffersize * 2);
            }
            else {
                break;
            }
        }
        description = QString::fromWCharArray(buffer);

        // now get the hardware id, which contains PID and VID.
        while(!SetupDiGetDeviceRegistryProperty(deviceInfo, &infoData,
            SPDRP_HARDWAREID, &data, (PBYTE)buffer, buffersize, &buffersize)) {
            if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                if(buffer) free(buffer);
                // double buffer size to avoid problems as per KB888609
                buffer = (LPTSTR)malloc(buffersize * 2);
            }
            else {
                break;
            }
        }

        unsigned int vid, pid;
        // convert buffer text to upper case to avoid depending on the case of
        // the keys (W7 uses different casing than XP at least).
        int len = _tcslen(buffer);
        while(len--) buffer[len] = _totupper(buffer[len]);
        if(_stscanf(buffer, _TEXT("USB\\VID_%x&PID_%x"), &vid, &pid) == 2) {
            uint32_t id;
            id = vid << 16 | pid;
            usbids.insert(id, description);
            LOG_INFO("USB VID: %04x, PID: %04x", vid, pid);
        }
        if(buffer) free(buffer);
    }
    SetupDiDestroyDeviceInfoList(deviceInfo);

#endif
    return usbids;
}