Exemple #1
0
int
usb_setup(char *name, size_t namelen)
{
	if (libusb_init(NULL) < 0) {
		return -1; 
	}
	
	if (libusb_pollfds_handle_timeouts(NULL) == 0) {
		printf("I'm too dumb to handle events on such an old system.\n");
		return -1;
	}
	
	for (d = devices; d->product_id; d += 1) {
		usb_dev = libusb_open_device_with_vid_pid(NULL, 0x6f8, d->product_id);
		if (usb_dev) {
			break;
		}
	}
	if (! usb_dev) {
		printf("Couldn't find a controller.\n");
		return -1;
	}
	
	// Figure out what it's called
	{
		int ret;
		struct libusb_device_descriptor ddesc;
		
		libusb_get_device_descriptor(libusb_get_device(usb_dev), &ddesc);
		ret = libusb_get_string_descriptor_ascii(usb_dev, ddesc.iManufacturer, (unsigned char *)name, namelen);
		if (ret > 0) {
			char *p = name + ret;
			
			*p = ' ';
			p += 1;
			ret = libusb_get_string_descriptor_ascii(usb_dev, ddesc.iProduct, (unsigned char *)p, namelen - ret - 1);
		}
		if (ret < 0) {
			printf("Warning: I can't figure out what to call this thing.\n");
		}
		printf("Opened [%s]\n", name);
	}
	
	usb_initiate_transfer();

	return 0;
}
Exemple #2
0
int usb_init(void) {
	int phase = 0;

	log_debug("Initializing USB subsystem");

	_libusb_log_source.file = "libusb";
	_libusb_log_source.name = "libusb";

#if defined(_WIN32) || defined(__APPLE__)
	libusb_set_log_function(usb_forward_message);
#endif

	switch (log_get_effective_level()) {
	case LOG_LEVEL_ERROR:
		putenv("LIBUSB_DEBUG=1");
		break;

	case LOG_LEVEL_WARN:
		putenv("LIBUSB_DEBUG=2");
		break;

	case LOG_LEVEL_INFO:
		putenv("LIBUSB_DEBUG=3");
		break;

	case LOG_LEVEL_DEBUG:
		if (log_is_included(LOG_LEVEL_DEBUG, &_libusb_log_source,
		                    LOG_DEBUG_GROUP_LIBUSB)) {
			putenv("LIBUSB_DEBUG=4");
		} else {
			putenv("LIBUSB_DEBUG=3");
		}

		break;

	default:
		break;
	}

	if (usb_init_platform() < 0) {
		goto cleanup;
	}

	phase = 1;

	// initialize main libusb context
	if (usb_create_context(&_context)) {
		goto cleanup;
	}

	phase = 2;

	if (!libusb_pollfds_handle_timeouts(_context)) {
		log_debug("libusb requires special timeout handling"); // FIXME
	} else {
		log_debug("libusb can handle timeouts on its own");
	}

	// create USB stack array. the USBStack struct is not relocatable, because
	// its USB transfers keep a pointer to it
	if (array_create(&_usb_stacks, 32, sizeof(USBStack), false) < 0) {
		log_error("Could not create USB stack array: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 3;

	if (usb_has_hotplug()) {
		log_debug("libusb supports hotplug");

		if (usb_init_hotplug(_context) < 0) {
			goto cleanup;
		}

		_initialized_hotplug = true;
	} else {
		log_debug("libusb does not support hotplug");
	}

	if (usb_rescan() < 0) {
		goto cleanup;
	}

	phase = 4;

cleanup:
	switch (phase) { // no breaks, all cases fall through intentionally
	case 3:
		array_destroy(&_usb_stacks, (ItemDestroyFunction)usb_stack_destroy);

	case 2:
		usb_destroy_context(_context);

	case 1:
		usb_exit_platform();

	default:
		break;
	}

	return phase == 4 ? 0 : -1;
}
static int usb_open(void *transport_config){
    int r;

    sco_state_machine_init();
    sco_ring_init();
    handle_packet = NULL;

    // default endpoint addresses
    event_in_addr = 0x81; // EP1, IN interrupt
    acl_in_addr =   0x82; // EP2, IN bulk
    acl_out_addr =  0x02; // EP2, OUT bulk
    sco_in_addr  =  0x83; // EP3, IN isochronous
    sco_out_addr =  0x03; // EP3, OUT isochronous    

    // USB init
    r = libusb_init(NULL);
    if (r < 0) return -1;

    libusb_state = LIB_USB_OPENED;

    // configure debug level
    libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING);
    
#ifdef HAVE_USB_VENDOR_ID_AND_PRODUCT_ID

    // Use a specified device
    log_info("Want vend: %04x, prod: %04x", USB_VENDOR_ID, USB_PRODUCT_ID);
    handle = libusb_open_device_with_vid_pid(NULL, USB_VENDOR_ID, USB_PRODUCT_ID);

    if (!handle){
        log_error("libusb_open_device_with_vid_pid failed!");
        usb_close(handle);
        return -1;
    }
    log_info("libusb open %d, handle %p", r, handle);

    r = prepare_device(handle);
    if (r < 0){
        usb_close(handle);
        return -1;
    }

#else
    // Scan system for an appropriate devices
    libusb_device **devs;
    ssize_t cnt;

    log_info("Scanning for USB Bluetooth device");
    cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0) {
        usb_close(handle);
        return -1;
    }

    int startIndex = 0;
    dev = NULL;

    while (1){
        int deviceIndex = scan_for_bt_device(devs, startIndex);
        if (deviceIndex < 0){
            break;
        }
        startIndex = deviceIndex+1;

        log_info("USB Bluetooth device found, index %u", deviceIndex);
        
        handle = NULL;
        r = libusb_open(devs[deviceIndex], &handle);

        if (r < 0) {
            log_error("libusb_open failed!");
            handle = NULL;
            continue;
        }
    
        log_info("libusb open %d, handle %p", r, handle);

        // reset device
        libusb_reset_device(handle);
        if (r < 0) {
            log_error("libusb_reset_device failed!");
            libusb_close(handle);
            handle = NULL;
            continue;
        }

        // device found
        r = prepare_device(handle);
        
        if (r < 0){
            continue;
        }

        libusb_state = LIB_USB_INTERFACE_CLAIMED;

        break;
    }

    libusb_free_device_list(devs, 1);

    if (handle == 0){
        log_error("No USB Bluetooth device found");
        return -1;
    }

    scan_for_bt_endpoints();

#endif
    
    // allocate transfer handlers
    int c;
    for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
        event_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers Events
        acl_in_transfer[c]  =  libusb_alloc_transfer(0); // 0 isochronous transfers ACL in
        if ( !event_in_transfer[c] || !acl_in_transfer[c]) {
            usb_close(handle);
            return LIBUSB_ERROR_NO_MEM;
        }
    }

    command_out_transfer = libusb_alloc_transfer(0);
    acl_out_transfer     = libusb_alloc_transfer(0);

    // TODO check for error

    libusb_state = LIB_USB_TRANSFERS_ALLOCATED;

#ifdef HAVE_SCO

    // incoming
    for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
        sco_in_transfer[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // isochronous transfers SCO in
        log_info("Alloc iso transfer");
        if (!sco_in_transfer[c]) {
            usb_close(handle);
            return LIBUSB_ERROR_NO_MEM;
        }
        // configure sco_in handlers
        libusb_fill_iso_transfer(sco_in_transfer[c], handle, sco_in_addr, 
            hci_sco_in_buffer[c], SCO_PACKET_SIZE, NUM_ISO_PACKETS, async_callback, NULL, 0);
        libusb_set_iso_packet_lengths(sco_in_transfer[c], ISO_PACKET_SIZE);
        r = libusb_submit_transfer(sco_in_transfer[c]);
        log_info("Submit iso transfer res = %d", r);
        if (r) {
            log_error("Error submitting isochronous in transfer %d", r);
            usb_close(handle);
            return r;
        }
    }

    // outgoing
    for (c=0; c < SCO_RING_BUFFER_COUNT ; c++){
        sco_ring_transfers[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // 1 isochronous transfers SCO out - up to 3 parts
    }
#endif

    for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
        // configure event_in handlers
        libusb_fill_interrupt_transfer(event_in_transfer[c], handle, event_in_addr, 
                hci_event_in_buffer[c], HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ;
        r = libusb_submit_transfer(event_in_transfer[c]);
        if (r) {
            log_error("Error submitting interrupt transfer %d", r);
            usb_close(handle);
            return r;
        }
 
        // configure acl_in handlers
        libusb_fill_bulk_transfer(acl_in_transfer[c], handle, acl_in_addr, 
                hci_acl_in_buffer[c] + HCI_INCOMING_PRE_BUFFER_SIZE, HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ;
        r = libusb_submit_transfer(acl_in_transfer[c]);
        if (r) {
            log_error("Error submitting bulk in transfer %d", r);
            usb_close(handle);
            return r;
        }
 
     }

    // Check for pollfds functionality
    doing_pollfds = libusb_pollfds_handle_timeouts(NULL);
    
    // NOTE: using pollfds doesn't work on Linux, so it is disable until further investigation here
    doing_pollfds = 0;

    if (doing_pollfds) {
        log_info("Async using pollfds:");

        const struct libusb_pollfd ** pollfd = libusb_get_pollfds(NULL);
        for (num_pollfds = 0 ; pollfd[num_pollfds] ; num_pollfds++);
        pollfd_data_sources = malloc(sizeof(data_source_t) * num_pollfds);
        if (!pollfd_data_sources){
            log_error("Cannot allocate data sources for pollfds");
            usb_close(handle);
            return 1;            
        }
        for (r = 0 ; r < num_pollfds ; r++) {
            data_source_t *ds = &pollfd_data_sources[r];
            ds->fd = pollfd[r]->fd;
            ds->process = usb_process_ds;
            run_loop_add_data_source(ds);
            log_info("%u: %p fd: %u, events %x", r, pollfd[r], pollfd[r]->fd, pollfd[r]->events);
        }
        free(pollfd);
    } else {
        log_info("Async using timers:");

        usb_timer.process = usb_process_ts;
        run_loop_set_timer(&usb_timer, AYSNC_POLLING_INTERVAL_MS);
        run_loop_add_timer(&usb_timer);
        usb_timer_active = 1;
    }

    return 0;
}