I have a windows 7 laptop (Sony pcg 81113M) with 3 USB ports, When I connect 2 * Ft 4222HQ and I run the "Getting start code for the Ft4222" (C++ Qtcreator) I get a wrong USB location which is 0x00. The same when I connect only one in that specific 2 ports.
I am verifying the USB-location of connected FTDI using the software USBview.
I am using "connect by location" in my program and if I connect two at the same time It will conseder it as one device (cause the Location Id is the same)
The FTDI driver is the latest version and i see all the interfaces in my device manager
Note: the third USB port works normally and I get a correct Location Id:
The os is a win7 64bit, the FTDI code runs on the 32bit (I also get the same result with 64bit)
Do anyone has an Idea about that? is there some other test that I can do it to figure it out the problem?
Here is Getting started FTDI code:
[source] https://www.ftdichip.com/Support/SoftwareExamples/LibFT4222-v1.4.4.zip
void ListFtUsbDevices()
{
FT_STATUS ftStatus = 0;
DWORD numOfDevices = 0;
ftStatus = FT_CreateDeviceInfoList(&numOfDevices);
for(DWORD iDev=0; iDev<numOfDevices; ++iDev)
{
FT_DEVICE_LIST_INFO_NODE devInfo;
memset(&devInfo, 0, sizeof(devInfo));
ftStatus = FT_GetDeviceInfoDetail(iDev, &devInfo.Flags, &devInfo.Type, &devInfo.ID, &devInfo.LocId,
devInfo.SerialNumber,
devInfo.Description,
&devInfo.ftHandle);
if (FT_OK == ftStatus)
{
printf("Dev %d:\n", iDev);
printf(" Flags= 0x%x, (%s)\n", devInfo.Flags, DeviceFlagToString(devInfo.Flags).c_str());
printf(" Type= 0x%x\n", devInfo.Type);
printf(" ID= 0x%x\n", devInfo.ID);
printf(" LocId= 0x%x\n", devInfo.LocId);
printf(" SerialNumber= %s\n", devInfo.SerialNumber);
printf(" Description= %s\n", devInfo.Description);
printf(" ftHandle= 0x%x\n", devInfo.ftHandle);
const std::string desc = devInfo.Description;
if(desc == "FT4222" || desc == "FT4222 A")
{
g_FT4222DevList.push_back(devInfo);
}
}
}
}
Main program:
int main(int argc, char const *argv[])
{
ListFtUsbDevices();
if(g_FT4222DevList.empty()) {
printf("No FT4222 device is found!\n");
return 0;
}
ftStatus = FT_OpenEx((PVOID)g_FT4222DevList[0].LocId, FT_OPEN_BY_LOCATION, &ftHandle);
if (FT_OK != ftStatus)
{
printf("Open a FT4222 device failed!\n");
return 0;
}
printf("\n\n");
printf("Init FT4222 as SPI master\n");
ftStatus = FT4222_SPIMaster_Init(ftHandle, SPI_IO_SINGLE, CLK_DIV_4, CLK_IDLE_LOW, CLK_LEADING, 0x01);
if (FT_OK != ftStatus)
{
printf("Init FT4222 as SPI master device failed!\n");
return 0;
}
printf("TODO ...\n");
printf("\n");
printf("UnInitialize FT4222\n");
FT4222_UnInitialize(ftHandle);
printf("Close FT device\n");
FT_Close(ftHandle);
return 0;
}
From https://ftdichip.com/wp-content/uploads/2020/08/TN_152_USB_3.0_Compatibility_Issues_Explained.pdf Section 2.1.2 Location ID Returned As 0
LocationIDs are not strictly part of the USB spec in the format
provided by FTDI. The feature was added as an additional option to
back up identifying and opening ports by index, serial number or
product description strings.
When connected to a USB 2.0 port the location is provided on the basis
of the USB port that the device is connected to. These values are
derived from specific registry keys. As the registry tree for 3rd
party USB 3.0 host drivers is different to the Microsoft generic
driver the Location ID cannot be calculated.
There is no workaround to this current issue and as such devices
should be listed and opened by index, serial number or product
description strings.
So this is known behaviour. Btw Win 7 EOL date was january 2020. Changing the OS is strongly adviced.
Related
I am trying to create a simple pose data app using Intel realsense with T265.
Since C examples database is very limited I am really struggling to start with this API.
Anyway here's my code:
/* Include the librealsense C header files */
#include <librealsense2/rs.h>
#include <librealsense2/h/rs_pipeline.h>
#include <librealsense2/h/rs_option.h>
#include <librealsense2/h/rs_frame.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// These parameters are reconfigurable //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define STREAM RS2_STREAM_ANY
#define FORMAT RS2_FORMAT_ANY
#define WIDTH 0
#define HEIGHT 0
#define FPS 0
#define STREAM_INDEX -1
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void check_error(rs2_error* e)
{
if (e)
{
printf("rs_error was raised when calling %s(%s):\n", rs2_get_failed_function(e), rs2_get_failed_args(e));
printf(" %s\n", rs2_get_error_message(e));
exit(EXIT_FAILURE);
}
}
void print_device_info(rs2_device* dev)
{
rs2_error* e = 0;
printf("\nUsing device 0, an %s\n", rs2_get_device_info(dev, RS2_CAMERA_INFO_NAME, &e));
check_error(e);
printf(" Serial number: %s\n", rs2_get_device_info(dev, RS2_CAMERA_INFO_SERIAL_NUMBER, &e));
check_error(e);
printf(" Firmware version: %s\n\n", rs2_get_device_info(dev, RS2_CAMERA_INFO_FIRMWARE_VERSION, &e));
check_error(e);
}
int main()
{
rs2_error* e = 0;
// Create a context object. This object owns the handles to all connected realsense devices.
// The returned object should be released with rs2_delete_context(...)
rs2_context* ctx = rs2_create_context(RS2_API_VERSION, &e);
check_error(e);
/* Get a list of all the connected devices. */
// The returned object should be released with rs2_delete_device_list(...)
rs2_device_list* device_list = rs2_query_devices(ctx, &e);
check_error(e);
int dev_count = rs2_get_device_count(device_list, &e);
check_error(e);
printf("There are %d connected RealSense devices.\n", dev_count);
if (0 == dev_count)
return EXIT_FAILURE;
// Get the first connected device
// The returned object should be released with rs2_delete_device(...)
rs2_device* dev = rs2_create_device(device_list, 0, &e);
check_error(e);
print_device_info(dev);
// Create a pipeline to configure, start and stop camera streaming
// The returned object should be released with rs2_delete_pipeline(...)
rs2_pipeline* pipeline = rs2_create_pipeline(ctx, &e);
check_error(e);
// Create a config instance, used to specify hardware configuration
// The returned object should be released with rs2_delete_config(...)
rs2_config* config = rs2_create_config(&e);
check_error(e);
// Request a specific configuration
rs2_config_enable_stream(config, STREAM, STREAM_INDEX, WIDTH, HEIGHT, FORMAT, FPS, &e);
check_error(e);
// Start the pipeline streaming
// The retunred object should be released with rs2_delete_pipeline_profile(...)
rs2_pipeline_profile* pipeline_profile = rs2_pipeline_start_with_config(pipeline, config, &e);
check_error(e);
while (1)
{
// This call waits until a new composite_frame is available
// composite_frame holds a set of frames. It is used to prevent frame drops
// The returned object should be released with rs2_release_frame(...)
rs2_frame* frames = rs2_pipeline_wait_for_frames(pipeline, RS2_DEFAULT_TIMEOUT, &e);
check_error(e);
// Returns the number of frames embedded within the composite frame
int num_of_frames = rs2_embedded_frames_count(frames, &e);
check_error(e);
int i;
for (i = 0; i < num_of_frames; ++i)
{
// The retunred object should be released with rs2_release_frame(...)
rs2_frame* frame = rs2_extract_frame(frames, i, &e);
check_error(e);
// Check if the given frame can be extended to depth frame interface
// Accept only depth frames and skip other frames
if (0 == rs2_is_frame_extendable_to(frame, RS2_EXTENSION_POSE, &e))
continue;
rs2_pose pose_data;
rs2_pose_frame_get_pose_data(frame, &pose_data, &e);
// Print the distance
printf("data %f, %f, %f\n", pose_data.translation.x, pose_data.translation.y, pose_data.translation.z);
rs2_release_frame(frame);
}
rs2_release_frame(frames);
}
// Stop the pipeline streaming
rs2_pipeline_stop(pipeline, &e);
check_error(e);
// Release resources
rs2_delete_pipeline_profile(pipeline_profile);
rs2_delete_config(config);
rs2_delete_pipeline(pipeline);
rs2_delete_device(dev);
rs2_delete_device_list(device_list);
rs2_delete_context(ctx);
return EXIT_SUCCESS;
}
And here's what I get from the console:
There are 2 connected RealSense devices.
Using device 0, an Intel RealSense T265
Serial number: my cams serialnumber
Firmware version: 0.2.0.951
rs_error was raised when calling
rs2_pipeline_start_with_config(pipe:00000000021 90DB0,
config:0000000002190E30):
No device connected
I always fail in rs2_pipeline_start_with_config function. I tried different config parameters but result is the same.
Let me also mention that I can run C++ pose sample which was delivered with the SDK with no problems. But I want to make it run using C.
Also, I don't know why it recognizes two same devices with the same serial number while only one T265 is connected to my PC.
In short:
I am trying to run the sel4 microkernel inside a x86_64 virtual machine and can't get the ethernet interface working.
What is the correct procedure to get internet connectivity (via a vitio-net ethernet device) on a sel4 microkernel? And what are the correct (memory) addresses?
Long version:
I have tried the camkes (picoserver) examples with the e1000 netdevice but couldn't get them to work so I decided to learn some new things and start from scratch. Also I decided to use virtio-net(together with vhost) instead of an emulated e1000 device for better performance. My plan is to use ethif_virtio_pci_init to initialise a eth_driver struct and then pass the struct on to picoTCP. For now I can find the virtio PCI device in sel4 but I am unsure how to correctly access it and create the ethif_virtio_pci_config_t needed for ethif_virtio_pci_init.
Some information from libethdrivers virtio_pci.h:
typedef struct ethif_virtio_pci_config {
uint16_t io_base;
void *mmio_base;
} ethif_virtio_pci_config_t;
/**
* This function initialises the hardware and conforms to the ethif_driver_init
* type in raw.h
* #param[out] eth_driver Ethernet driver structure to fill out
* #param[in] io_ops A structure containing os specific data and
* functions.
* #param[in] config Pointer to a ethif_virtio_pci_config struct
*/
int ethif_virtio_pci_init(struct eth_driver *eth_driver, ps_io_ops_t io_ops, void *config);
so for the ethif_virtio_pci_config_t I need an uint16_t io_base address and a pointer to the MMIO base.
This is the information I have obtained so far:
Found virtio_net_pci device
BASE_ADDR[0] ----
base_addr_space[0]: 0x1 [PCI_BASE_ADDRESS_SPACE_IO]
base_addr_type[0]: 0x0 [ 32bit ]
base_addr_prefetchable[0]: no
base_addr[0]: 0xc000
base_addr_size_mask[0]: 0xffffffe0
BASE_ADDR[1] ----
base_addr_space[1]: 0x0 [PCI_BASE_ADDRESS_SPACE_MEMORY]
base_addr_type[1]: 0x0 [ 32bit ]
base_addr_prefetchable[1]: no
base_addr[1]: 0xfeb91000
base_addr_size_mask[1]: 0xfffff000
BASE_ADDR[2] ----
BASE_ADDR[3] ----
BASE_ADDR[4] ----
base_addr_space[4]: 0x0 [PCI_BASE_ADDRESS_SPACE_MEMORY]
base_addr_type[4]: 0x4 [ 64bit ]
base_addr_prefetchable[4]: yes
base_addr[4]: 0xfe000000
base_addr_size_mask[4]: 0xffffc000
BASE_ADDR[5] ----
As far as I understand I now need to map the pysical address to a virtual one. For that I created an IO-mapper but I am not sure what to map. The whole dma region starting at 0x8000000 or just the address of the virtio device? As far as I understand the new virtual address would be my MMIO base pointer but what is the uint16_t io_base than?
This is my code so far, the part I am unsure about is at the end:
#define ALLOCATOR_STATIC_POOL_SIZE ((1 << seL4_LargePageBits) * 10)
static simple_t simple;
static ps_io_mapper_t io_mapper;
static char allocator_mem_pool[ALLOCATOR_STATIC_POOL_SIZE];
static vka_t vka;
static vspace_t vspace;
static sel4utils_alloc_data_t data;
static ltimer_t timer;
int main() {
PRINT_DBG("Hello World\n");
seL4_BootInfo *info = platsupport_get_bootinfo();
simple_default_init_bootinfo(&simple, info);
/* print out bootinfo and other info about simple */
// simple_print(&simple);
allocman_t *allocman = bootstrap_use_current_simple(&simple, ALLOCATOR_STATIC_POOL_SIZE, allocator_mem_pool);
if (allocman == NULL) {
ZF_LOGF("Failed to create allocman");
}
allocman_make_vka(&vka, allocman);
int error = sel4utils_bootstrap_vspace_with_bootinfo_leaky(&vspace,
&data, simple_get_pd(&simple),
&vka, info);
if (error != 0) {
PRINT_DBG("Failed to create virtual memory manager. Error: %d\n", error);
return -1;
}
error = sel4platsupport_new_io_mapper(&vspace, &vka, &io_mapper);
if (error != 0) {
PRINT_DBG("Failed to create io mapper. Error: %d\n", error);
return -1;
}
ps_io_ops_t io_ops;
error = sel4platsupport_new_io_ops(&vspace, &vka, &simple, &io_ops);
if (error != 0) {
PRINT_DBG("Failed to create io ops. Error: %d\n", error);
return -1;
}
ps_io_port_ops_t port_ops;
int error = sel4platsupport_get_io_port_ops(&port_ops, &simple, &vka);
if (error != 0) {
PRINT_DBG("Failed to find io port ops. Error: %d\n", error);
return -1;
}
printf("Start scannning\n");
libpci_scan(port_ops);
PRINT_DBG("Found %u devices\n", libpci_num_devices);
for (uint32_t i = 0; i < libpci_num_devices; ++i) {
PRINT_DBG("PCI device %u. Vendor id: %x. Device id: %x\n",
i, libpci_device_list[i].vendor_id, libpci_device_list[i].device_id);
}
libpci_device_t* virtio_net_pci = libpci_find_device(0x1af4, 0x1000);
if (!virtio_net_pci) {
PRINT_DBG("Failed to find the virtio_net_pci device\n");
// return -1;
}else{
// libpci_device_iocfg_debug_print(&virtio_net_pci->cfg,true);
PRINT_DBG("Found virtio_net_pci device\n");
libpci_device_iocfg_debug_print(&virtio_net_pci->cfg,false);
}
//Now what?
unsigned long phys = 0x8000000; //what physical address to map?
void *mmio_ptr = ps_io_map(&io_mapper, phys, 4096, 0, PS_MEM_NORMAL);
memset(ptr, 0, 4096);
if (mmio_ptr == NULL) {
PRINT_DBG("Failed to map phys addr. Error: %p\n", ptr);
return -1;
}
ethif_virtio_pci_config_t me_config;
me_config.mmio_base = mmio_ptr; //is this correct?
//me_config.io_base = ?
I read alot about the sel4 kernel but I am still new to most of the concepts of the sel4 microkernel (and Linux kernel) so I am very grateful for any tipps and recommendations. I am normally working with embedded, microcontrollers and more "bare metal" platforms and wanted to learn something new but for now alot is very confusing.
I have been playing around with a userspace application based on uvc driver based on v4l2. I have been trying to get the capabilities of my integrated webcam (this is a laptop), and then I got into one problem. My driver does not set any video standard flags against VIDIOC_ENUMINPUT ioctl. Following is my code.
struct v4l2_capability caps;
memset(&caps, 0, sizeof(caps));
if(-1 == ioctl(fd, VIDIOC_QUERYCAP, &caps)) {
perror("Unable to query capabilities");
return errno;
}
printf(
"-------- VIDIOC_QUERYCAP --------\n"
"Driver = %s\n"
"Card = %s\n"
"Bus Info = %s\n"
"Version = %d\n"
"Capabilities = %#x\n"
"Device Caps = %#x\n",
caps.driver,
caps.card,
caps.bus_info,
caps.version,
caps.capabilities,
caps.device_caps);
int index;
if(-1 == ioctl(fd, VIDIOC_G_INPUT, &index)) {
perror("Unable to get current input index");
return errno;
}
struct v4l2_input input;
memset(&input, 0, sizeof(input));
input.index = index;
if(-1 == ioctl(fd, VIDIOC_ENUMINPUT, &input)) {
perror("Unabel to query attributes of video input");
return errno;
}
printf(
"--------- VIDIOC_ENUMINPUT ---------\n"
"Index = %d\n"
"Name = %s\n"
"Type = %d\n"
"Audio Set = %d\n"
"Video Stds = %lld\n"
"Status = %d\n"
"Capabilities = %d\n",
input.index,
input.name,
input.type,
input.audioset,
input.std,
input.status,
input.capabilities);
And the output looks like the following.
-------- VIDIOC_QUERYCAP --------
Driver = uvcvideo
Card = Integrated_Webcam_HD: Integrate
Bus Info = usb-0000:00:1d.0-1.6
Version = 266001
Capabilities = 0x84200001
Device Caps = 0x4200001
--------- VIDIOC_ENUMINPUT ---------
Index = 0
Name = Camera 1
Type = 2
Audio Set = 0
Video Stds = 0 // <--- Problem here.
Status = 0
Capabilities = 0
Notice that the video standards flag is set to 0. To further drill down the problem, I tried VIDIOC_G_STD ioctl, as follows,
struct v4l2_standard std;
memset(&std, 0, sizeof(std));
if(-1 == ioctl(fd, VIDIOC_G_STD, &std)) {
perror("Error");
return errno;
}
But receives the following error.
Error: Inappropriate ioctl for device
What could be the conclusion? Am I doing anything wrong here?
Platform Details
Linux linux 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Driver version: 4.15.17
Device node : /dev/video0 (only one device)
I think I found the answer myself. On closer evaluation, I have found that the integrated webcam on my laptop is on the USB bus internally. USB class devices are an exception for v4l2 video standard ioctl. As per the documentation,
Special rules apply to devices such as USB cameras where the notion of video standards makes little sense. More generally for any capture or output device which is incapable of capturing fields or frames at the nominal rate of the video standard, or that does not support the video standard formats at all. Here the driver shall set the std field of struct v4l2_input and struct v4l2_output to zero and the VIDIOC_G_STD, VIDIOC_S_STD, ioctl VIDIOC_QUERYSTD and ioctl VIDIOC_ENUMSTD ioctls shall return the ENOTTY error code or the EINVAL error code.
Thus, I think my camera falls into one of these categories, and STD query is not really applicable in my case. I'm not sure if this is true for MIPI or Parallel buses. I will update once I do a little more experiment with those hardware.
I'm trying to interface with a USB peripheral using libusb-1.0 in cygwin.
libusb_get_device_list(...) works fine, I get a list of USB devices. It finds the device with the correct VendorID and ProductID in the device list, but when libusb_open(...) is called with that device, it always fails with the error code LIBUSB_ERROR_NOT_FOUND.
I don't think it's a permission issue, I've tried running this as admin, and there's a separate error code (LIBUSB_ERROR_ACCESS) for that. This same code works with libusb-1.0 in Linux.
unsigned init_usb(int vendor_id, int product_id, int interface_num)
{
int ret = libusb_init(NULL);
if (ret < 0) return CONTROL_ERROR;
libusb_device **devs = NULL;
int num_dev = libusb_get_device_list(NULL, &devs);
libusb_device *dev = NULL;
for (int i = 0; i < num_dev; i++) {
struct libusb_device_descriptor desc;
libusb_get_device_descriptor(devs[i], &desc);
if (desc.idVendor == vendor_id && desc.idProduct == product_id) {
dev = devs[i];
break;
}
}
if (dev == NULL) return CONTROL_ERROR;
libusb_device_handle *devh = NULL;
ret = libusb_open(dev, &devh);
//ret is always -5 here (in cygwin)!
if (ret < 0) return CONTROL_ERROR;
libusb_free_device_list(devs, 1);
return CONTROL_SUCCESS;
}
It turns out this was a kind of driver issue. I had to tell Windows to associate the particular device I'm using with the libusb drivers.
libusb-win32-1.2.6.0 comes with some tools to make that association (although you may need to configure your system to allow the installation of unsigned drivers).
There's one tricky bit. If you just want to associate the device with libusb, you can use the inf-wizard.exe tool to make that association, but that will change the primary association to be with libusb. In my case, the device is a USB Audio Class device (i.e. USB sound card) that also has some libusb functionality. When I used inf-wizard.exe, libusb started working (yay!), but then it stopped working as an audio device.
In my case, I needed to use the install-filter-win.exe tool to install a filter driver for libusb. That allows the device to still show up as a USB Audio device, but also interact with it using libusb.
I have a cheap PS3 controller and a NEO-GEO X controller. They are both detected on eg. Fedora 20 and a Lubuntu 14.04. They appear in lsusb
Bus 001 Device 012: ID 0e8f:0003 GreenAsia Inc. MaxFire Blaze2
Bus 001 Device 016: ID 1292:4e47 Innomedia
The devices appear underneath /dev/input. Running udevadm on them both shows that the GreenAsia device uses the pantherlord driver whereas the other device uses hid-generic
If I run the following test code only the GreenAsia device is reported by SDL. If I unplug it then the other device is detected. Is this a known limitation of SDL or some other issue?
// from http://www.libsdl.org/release/SDL-1.2.15/docs/html/guideinput.html
#include "SDL/SDL.h"
int main () {
if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0)
{
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
exit(1);
}
printf("%i joysticks were found.\n\n", SDL_NumJoysticks() );
printf("The names of the joysticks are:\n");
for( int i=0; i < SDL_NumJoysticks(); i++ )
{
printf(" %s\n", SDL_JoystickName(i));
}
return 0;
}
The answer to my question appears to be "no" if only one of the joysticks maps to a device /dev/input/event13 or similar, which is what happens to my PS3 controller in my case.
In SDL_SYS_JoystickInit there is the following code
#if SDL_INPUT_LINUXEV
/* This is a special case...
If the event devices are valid then the joystick devices
will be duplicates but without extra information about their
hats or balls. Unfortunately, the event devices can't
currently be calibrated, so it's a win-lose situation.
So : /dev/input/eventX = /dev/input/jsY = /dev/jsY
*/
if ( (i == 0) && (numjoysticks > 0) )
break;
#endif
When i is 0 it is looking for the "event" devices. My PS3 controller gets devices /dev/input/event13 and /dev/input/js1, but my NEO-GEO X controller only has the device /dev/input/js0, so breaking from the loop causes it to get ignored.
A workaround in this case is to add the device that doesn't have a corresponding "event" device to SDL_JOYSTICK_DEVICE
Thanks to Brian McFarland with the help in getting to the bottom of this.