I'd like to write a Ruby program for OSX that communicates via USB with my Arduino.
I am going to use the serialport gem for that purpose.
I found a sample code that says:
port_str = "/dev/ttyUSB0" #may be different for you
How can I scan and find the Arduino, and know to what port I should connect to automatically?
(I have OSX)
Thanks!
This can be tricky to do in a general way, because Arduino devices appear as USB serial ports, making it hard to distinguish between Arduino and non-Arduino ports.
The brute-force approach is: enumerate the USB serial devices, open() each in turn, and see if your firmware boot header is sent on the other end. On OSX, the USB serial devices are at /dev/tty.*, but that may change with future OS updates. This method works, but can be slow and timing sensitive. I've found that a startup delay on the Arduino before sending a header helps, as well as a simple "hello, are you there?" command the host can use to bang for signs of life.
Also, you can save the last port found so that subsequent app launches try that port first.
A variant: if your app asks the user to plug in the Arduino at startup, you can list the USB ports in /dev, wait for user to confirm it's plugged in, and list the ports again. Any newly appearing device is likely your Arduino.
At the next level, you could look at the USB Vendor and Product IDs (VID & PID). However, these IDs are all over the map in Arduino-land. They differ by model, version, revision, Chinese clones, and the various Arduino-compatible devices. See this writeup at Adafruit.
If you're just trying to make things work with a very narrow hardware set (e.g. the one Arduino on your bench), you can use this OSX command to see the USB device details:
system_profiler SPUSBDataType
With my system, I get:
...
USB Bus:
Host Controller Location: Built-in USB
Host Controller Driver: AppleUSBUHCI
PCI Device ID: 0x7fff000027c9
PCI Revision ID: 0x7fff00000002
PCI Vendor ID: 0x7fff00008086
Bus Number: 0x3d
Communication Device:
Product ID: 0x0043
Vendor ID: 0x2341
Version: 0.01
Serial Number: 75331313133351800000
Speed: Up to 12 Mb/sec
Manufacturer: Arduino (www.arduino.cc)
Location ID: 0x3d100000 / 2
Current Available (mA): 500
Current Required (mA): 100
The location ID (0x3d100000 / 2) seems to match up with the device name: /dev/cu.usbmodem3d11
See this question for running command line commands from within a Ruby script.
Related
I am recently read documentation about Windows-Driver-Model, one of a chapter of it says :
Before a driver is installed for a new device, the bus or hub driver to which the device is connected assigns a hardware identifier (ID) to the device.
But how ??
For example the OS want to communicate with a USB device.
How can it ( the os ) obtain the hardware-id of the device ?
Is there some kind of protocol to communicate with the hardware that works like :
The OS send a signal ( or USB formatted message ) with a body of such as "I want to know hardware-id"
The hardware must response to this message to OS with a body of such as "My hardware-id is xxx"
If there is a protocol like this, could you please told me the "standard" of such a protocol.
On most modern computers every USB hub is connected to one xHCI controller (https://wiki.osdev.org/EXtensible_Host_Controller_Interface). At boot the BIOS will build ACPI tables in RAM that the OS will look for in conventional positions. Once the OS finds these tables, it will look at every entry to determine what devices are plugged to the computer including xHCI controllers. As stated on osdev.org
All xHCI controllers will have a Class ID of 0x0C, a Sublcass ID of 0x03, and an Interface value of 0x30. The configuration space for this device will contain two Base Address Registers: BAR0 and BAR1. These two 32-bit address fields combine to create a single 64-bit address that points to the base address of the memory mapped registers for the controller.
The memory mapped register of the xHCI s are then used to send commands to the USB device including commands to get the device descriptor of the USB device. The document on https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf is the spec for the xHCI. So if you want to really understand how it works under the hood then this is a great place to look at.
I want to get from a Windows COM port name (COM11) to the serial number of the USB device that provides that COM port (I'm presently working with FTDI adapters, if that matters).
I can use SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, NULL, NULL, DIGCF_PRESENT) to enumerate the ports on the system, then I can use SetupDiEnumDeviceInfo and SetupDiGetDeviceRegistryProperty to get the vid/pid out of the Hardware ID.
But I can't seem to figure out a way to get hold of the serial number.
The objective is to program the serial adapters with serial numbers that identify their usage for a simulator program we've got (so the user doesn't have to figure out which adapter is which COM port).
You can try using SetupDiGetDeviceInstanceId to get the Device Instance ID of USB device, which should be a string of the form USB\VID_xxxx&PID_xxxx\[ID]. If your USB device is not composite, then [ID] would be the serial number. This is how libusbp obtains the serial number of a USB device.
If your device is composite, the serial port would be a child device and you would have to go up one level to find the parent that represents the actual USB device, which should have the device instance ID that you care about.
Before writing any code, I'd recommend checking the Device Instance ID in your Device Manager, where it is known as "Device Instance Path".
To make you feel somewhat better about extracting the serial number from a string that has other information, the Device Instance ID is documented by Microsoft here:
https://learn.microsoft.com/en-us/windows-hardware/drivers/install/device-instance-ids
I want to get the Device descriptor of USB devices on my system. I am creating a userspace application in Windows(un-managed, native c++ ). From these descriptors, I want to identify billboard devices and parse billboard capability descriptor (parsing bos descriptor).
Here is my approach.
Get USB devices on a system by SetupDiGetClassDevs(&GUID_CLASS_USB_DEVICE,...)
Get device path of each device using SetupDiGetDeviceInterfaceDetail()
Use CreateFile() on device path to get handle to the device.
Issue IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION IOCTL using DeviceIoControl(), and the handle, to get the device descriptor.
I am stuck on the 4th step (getLastError() - Invalid Function).
Other projects (like this sample code from Intel), enumerate all USB controllers on the system, root hubs, ports, and interfaces, and issue IOCTL on the root hub's handle, specifying the port number to which a device is connected.
I do not want to concern myself with the USB hierarchy of the system.
It is less error-prone and easier to get USB devices in the system using setup API. However, nowhere I can see IOCTL being issued to them directly.
Update1
From learn.microsoft.com:
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION I/O control request retrieves one or more descriptors for the device that is associated with the indicated port index. This request targets the USB hub device (GUID_DEVINTERFACE_USB_HUB). Thus this ioctl which can give me device descriptor of a USB device is meant to be handled by USB Hub, and NOT by a USB device.
Therefore the other solutions pass handle of hub to DeviceIoControl(), as can be seen on Line 68 of the source code from Intel (Linked here).
I instead want to use the handle obtained in step 3 (handle of the device) above to get the device descriptor. So, the IOCTL could be different, or possibly there is a way to get handle of the hub, and index of port to which the device is connected using the handle of the USB device.
The way I see it, device descriptor is an intrinsic property of a USB device, and therefore there must be a way to get it directly from the USB device.
Assuming you already have USB device handle first you need to get DEVPKEY_Device_Driver property string from it (by means of CM_Get_DevNode_PropertyW or SetupDiGetDevicePropertyW).
You'll receive string like {36fc9e60-c465-11cf-8056-444553540000}\0010.
Next you need to iterate over each USB hub in system (devices that have GUID_DEVINTERFACE_USB_HUB interface) and for each:
Open it via CreateFile() call
Call DeviceIoControl(hubInterfaceHandle, IOCTL_USB_GET_NODE_INFORMATION, ...) to get USB_NODE_INFORMATION structure that contains number of USB ports in its hubInfo.u.HubInformation.HubDescriptor.bNumberOfPorts
For each port from 1 (they are one based!!!) to bNumberOfPorts call DeviceIoControl(hubInterfaceHandle, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ...) to get unique DriverKey of device connected to this port.
Compare DriverKey string you have on previous step with string you have from DEVPKEY_Device_Driver call. If they are same - congratulations you have found USB hub and port that have your USB device connected!
Now you can call DeviceIoControl(usbHubInterfaceHandle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, ...) to get USB_NODE_CONNECTION_INFORMATION structure that contains USB_DEVICE_DESCRIPTOR!
Also you can additionally call DeviceIoControl(usbHubInterfaceHandle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ...) with USB_DESCRIPTOR_REQUEST to get other USB descriptors in addition to basic USB_DEVICE_DESCRIPTOR.
For example code see EnumerateHubPorts() and GetDriverKeyName() in official USBView sample.
Also I just did that in my RawInputDemo repo here.
UPDATE: There is easier way to get USB device number in a parent USB HUB - just get DEVPKEY_Device_Address property from a USB devnode.
How does windows identify a USB device uniquely, even though the device data supplied from the USB device is common to all devices of that make ?
To state this alternatively, Windows can distinguish between two instances of Dell keyboards of same model, without the keyboard supplying any unique serial number. What is the exclusive data field windows searches for when initializing the USB device ?
Windows uses Device Instance ID for identification. As you can see in the documentation it contains a device part and an instance part.
The device part is taken from a USB device.
It is up to a bus driver how to generate the instance part. The bus driver cannot solely rely on the information returned from the usb device. Because two identical devices will break the system - Device Instance IDs must be unique! So usually it appends additional info - port number and etc (the exact algorithms is unknown and depends on driver manufacturer). Also PNP manager can add more uniqueness to the Instance ID.
When we connect a device to the host the device, enumeration process will happen, At the end of this process, the host will supply a unique address to the newly connected device. So each device connected to the system will have a unique Id which is supplied by the system, using this id devices can be identified and the communication happens
I am running a USB cell modem via PPP in Embedded Linux. I can use AT commands via minicom to connect to the modem and interrogate the signal strength (AT+CSQ) when the PPP connection is not active. However, when it's active, this is not possible.
Is there any way to retrieve the signal strength from a PPP connected USB cell modem while the PPP connection is being used? I am open to an API or any other method available.
I don't have a umw190, but the Linux driver for the modem should have more than one ttyACM character device available. Use one for PPP and the other for AT+CSQ. Check dmesg for cdc_acm to see.
If your embedded device has udev then both devices should automagically appear in /dev. If not you'll have to mknod more. Off the top of my head major number is 166 for cdc_acm.
What does the physical setup look like?
1. Are you using a modem that is on a board designed/printed by the same company as your SBC?
2. Is it connected via something like PC104 serial or USB?
3. What specific modem are you using?