How would you send data through the USB port and receive the data in my Linux machine?
task main ()
{
byte data[2] = {1,2};
while (1)
{
Wait(1000);
SetUSBOutputBuffer(0, 2, data);
}
}
Compiled it with:
nbc -d -Z2 usb.nxc
dmesg:
usb 2-1.2: reset full-speed USB device number 6 using ehci_hcd
Now how do I get the "data" what was sent by the NXT?How would I write a Linux program in C that would read the USB buffer?
The Fantom SDK doesn't support Linux. Instead, use libnxt. The one in the Debian repositories is still being maintained.
Related
I want to make a custom program that will allow me to interface a Salae Logic usb logic analyzer. So first and foremost I looked upon for any info regarding the usb in my linux box:
$ lsusb
Bus 002 Device 002: ID 05e3:0732 Genesys Logic, Inc. All-in-One Cardreader
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 001 Device 002: ID 4e53:5407
Bus 001 Device 004: ID 0925:3881 Lakeview Research Saleae Logic
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Dmesg:
[ 428.549560] usb 1-6: new high-speed USB device number 4 using xhci_hcd
[ 428.697722] usb 1-6: New USB device found, idVendor=0925, idProduct=3881, bcdDevice= 0.01
[ 428.697727] usb 1-6: New USB device strings: Mfr=0, Product=0, SerialNumber=0
Is seems that does not expose a serial device like arduino (or any other FTDI interfacing device) like modems:
[ 766.906266] usb 1-5: new full-speed USB device number 5 using xhci_hcd
[ 767.056746] usb 1-5: New USB device found, idVendor=2341, idProduct=0043, bcdDevice= 0.01
[ 767.056752] usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=220
[ 767.056756] usb 1-5: Manufacturer: Arduino (www.arduino.cc)
[ 767.056759] usb 1-5: SerialNumber: 7533131313335170A061
[ 767.088804] cdc_acm 1-5:1.0: ttyACM0: USB ACM device
[ 767.089110] usbcore: registered new interface driver cdc_acm
[ 767.089110] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
So supposedly I want to make a C++ (or any other language) software where I can read data from it how I can make my application to have access to a non usb-to-serial interfacing device?
I mean for an arduino I could use the POSIX open as the example shows from this link:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
/*
* 'open_port()' - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int open_port(void){
int fd; /* File descriptor for the port */
fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
/*
* Could not open the port.
*/
perror("open_port: Unable to open /dev/ttyS0 - ");
} else{
fcntl(fd, F_SETFL, 0);
}
return (fd);
}
But in my case I have no such a file descriptor to begin with according to dmesg.
Normally something like this is done with libusb, at least when you are in userspace (which your question suggests you are).
USB transfers are a lot more complicated than a USB UART though, so brace yourself to deal with different endpoints, pipes, transfer modes and co
I'm writing a small C application to run on my (Linux) QNAP NAS that will talk to an Arduino (I have no difficulty with any of the USB code for the arduino). (The arduino has a trusted application on it that accepts text commands via USB serial.)
My wish was to find it using the USB vendor/product IDs (only half implemented at the moment). What I have so far (see below) works quite nicely in that it does find the device.
// runs on NAS
#include <stdio.h>
#include <usb.h>
main () {
struct usb_bus *bus;
struct usb_device *dev;
usb_init();
usb_find_busses();
usb_find_devices();
for (bus = usb_busses; bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
printf("Trying %s/%s\n", bus->dirname, dev->filename);
printf("\tVendor = 0x%04x\n", dev->descriptor.idVendor);
printf("\tBus = 0x%03x\n", bus->location);
printf("\tFile = %s\n", dev->filename);
if (dev->descriptor.idVendor==0x403) {
printf("\t HEY, THIS IS MINE!\n");
usb_dev_handle *handle = usb_open(dev);
printf("\t HANDLE 0x%08x\n", (int) handle);
//printf(handle, "1,5,62,75\n");
usb_close(handle);
}
}
}
}
The trouble is that now I want to send/receive a little bit of text with the device and I don't know how to do that.
I have expected I should be generating a device name from something in the usb_device struct and then open it like a file (like one would do on Windows).
If that's correct, I need to know the correct way to find out the device name...
I believe I'm using libusb.
I happen to know that -- as currently configured/connected -- it's ttyUSB0 but I'd like to know that using code.
thank you!
I suggest using libusbp. It is a C library with a C++ wrapper, and there is example code showing how to get the name of a serial port based on the vendor ID and product ID of the USB device:
https://github.com/pololu/libusbp/blob/master/examples/port_name/port_name.cpp
libusb is a library used for low level communication with USB devices. But when your communication is limited just to reading device's USB descriptor - libusb is not the best tool.
Linux systems use udev subsystem to manage hot-plug devices. udev reads descriptors of all plugged USB devices and stores them in its database. libudev is the library that you should use to get such info like device names of enumerated devices. In your case you need to remember that usb_device and usb_interface are separate things - only the latter would have the tty device file assigned to it.
Alternatively you could just use udev config to assign a constant device name to your specific device. So you would not have to be looking for it.
An acquisition system based on a FPGA and a micro-controller is using two FTDI (FT2232H) devices. Basically, the FPGA is generating data (as fast as possible) and sending to a system processor via the FT2232H (asynchronous FIFO mode). Also, the micro-controller is connected to the system processor via another FTDI device in UART mode.
(clickable, from http://postimg.org/image/ovpov6ujv/)
The whole system is already working on Windows platform with success, reaching ~95MB/s in the FTDI mode using the D2XX driver. The other FTDI device IC is connected using Virtual COM driver and the data throughput is not measured (don't need to go fast).
On Linux the results are different. For both devices (UART and FIFO mode) the FTDI's D2XX direct driver is used.
The data transmitted via FIFO mode IC is droping byte (about 10% of the total data, 30MB). The received data from the UART mode IC contain unexpected values. The function FT_GetQueueStatus return without error and the field RxBytes greater than zero (0) even if the micro-controller don’t send any data via UART. The data received usually is something like 0x01 and 0x60, multiples times. The frequency change when the latency time change.
Below the test case details.
Setup the device:
ftStatus |= FT_ResetDevice(*ftHandle); //Reset USB device
ftStatus |= FT_Purge(*ftHandle, FT_PURGE_RX | FT_PURGE_TX); // Purge transmit and receive buffers
ftStatus |= FT_SetUSBParameters(*ftHandle, USB_TRANSFER_SIZE, 0); //Set USB request transfer size
ftStatus |= FT_SetTimeouts(*ftHandle, 100, 100); //Sets the read and write timeouts in milliseconds for the FT2232H
ftStatus |= FT_SetLatencyTimer(*ftHandle, 4); //Set the latency timer
// For the device using UART mode, the following function are also executed:
if(serial) {
ftStatus |= FT_SetBitMode(*ftHandle, 0x00, 0); //Turn off bit bang mode
ftStatus |= FT_SetBaudRate(*ftHandle, 9600); // Set baud rate to 9600
ftStatus |= FT_SetDataCharacteristics(*ftHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); // Set to communicate at 8N1
ftStatus |= FT_SetFlowControl(*ftHandle, FT_FLOW_NONE, 0, 0); // Disable hardware / software flow control
}
Read data:
dwNumInputBuffer = USB_TRANSFER_DATA_SIZE;
ftStatus = FT_Read(ftHandle, &InputBuffer, dwNumInputBuffer,
&dwNumBytesRead); //Read out the data from input buffer
if (ftStatus != FT_OK) {
printf("Fail reading from USB device!\n");
done = 1;
}
if (dwNumBytesRead > 0) {
// move the data to other location memory (and process once all the expected data is received)
}
The system specification:
Windows 7 64 bit, 64GB RAM, SSD hard disk:
FIFO mode IC: D2XX library release date: 2014-09-29
UART mode IC: VCP Drivers release date: 2014-09-29
Ubuntu 14.04 64bits, 8GB RAM, standard hard disk:
FIFO mode IC: D2XX library release date: 2012-06-29, 1.1.12
UART mode IC: D2XX library release date: 2012-06-29, 1.1.12
The D2XX library is used for both FTDI devices because the USB-SERIAL driver need to be shutdown according with FTDI suggestions FTDI Drivers Installation Guide for Linux. When using one (1) UART mode FTDI device and USB-SERIAL driver (standard with Linux Kernel) the application don't receive unexpected results.
Thanks for any suggestions.
I read from LDD3 chapter 14 about hotplug drivers.I need to write a usb mouse driver which load when I plug the hardware. Now, doing some experiment I come to know that there is a driver named "hid-generic" which is called when plug-unplug.
[ 6654.232046] usb 3-1: new low-speed USB device number 3 using uhci_hcd
[ 6654.462061] usb 3-1: New USB device found, idVendor=093a, idProduct=2510
[ 6654.462067] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 6654.462071] usb 3-1: Product: USB OPTICAL MOUSE
[ 6654.462074] usb 3-1: Manufacturer: PIXART
[ 6654.489316] input: PIXART USB OPTICAL MOUSE as /devices/pci0000:00/0000:00:1d.1/usb3/3-1/3-1:1.0/input/input12
[ 6654.489445] hid-generic 0003:093A:2510.0004: input,hidraw0: USB HID v1.10 Mouse [PIXART USB OPTICAL MOUSE] on usb-0000:00:1d.1-1/input0
Also lsmod shows,
Module Size Used by
hid_generic 12541 0
usbhid 47259 0
hid 105241 2 hid_generic,usbhid
psmouse 102541 0
My doubts are as follows,
1) To make my module load (hotplug) when this mouse plugs in, I have to disable these 3 drivers in kernel and build whole kernel with my driver with vendor and device ID in id_table. Right?
2) I also read about USB core drivers and USB device drivers. So these HID drivers are core drivers or device drivers?
3) Which are core drivers and device driver in case of USB mouse? And where can I find them in kernel source?
Thanks,
Sunil.
I'll try to answer your questions one by one :
1) To make my module load (hotplug) when this mouse plugs in, I have to disable these 3 drivers in kernel and build whole kernel with my driver with vendor and device ID in id_table. Right?
Yes, but there are some additional things you need to take care of. First understand how a particular module(driver) gets loaded. The key to this is MODULE_DEVICE_TABLE(usb, &my_id_table); Whenever a particular module is "installed" (using make modules_install), an entry, according to the id table passed in MODULE_DEVICE_TABLE gets created in /lib/modules/<your_kernel>/modules.usbmap and /lib/modules/<your_kernel>/modules.dep file(search for the string "usbhid" in the files). Whenever a new usb device is detected, the kernel reads these files to find the matching parameters. If it is found, the following module is loaded from the corresponding path found in /lib/modules/<your_kernel>/modules.dep which holds the info. about the path where the driver is located and also its dependencies.
So, now even if you unload(rmmod) usbhid from the kernel, it will be loaded again when you re-insert your mouse. To avoid this from happening you need to modify those files, i.e. remove the entries from the files. To do so, "move" the usbhid driver from its original path(generally located at /lib/modules/<your_kernel>/kernel/drivers/hid/usbhid/usbhid.ko to a safe place. Now rebuild the dependencies such that the entries would be removed from the dependency files.
Now you need to create entries of your driver. Just install your driver and you are good to go!
So, to summarize :
$ sudo rmmod usbhid # Unload the usb mouse driver
$ cd /lib/modules/$(uname -r)/ # Move to your current kernel
$ vim modules.usbmap # Check for the "usbhid" string
$ vim modules.dep # Check for "usbhid.ko:" string
$ sudo mv kernel/drivers/hid/usbhid/usbhid.ko ~/Desktop # Take backup of your current
usb mouse driver
$ sudo depmod -a # Rebuild the dependency files
Now check the dependency files for the string "usbhid" again. It shouldn't be there!
$ cd /path/to/your/driver
$ sudo make modules_install # Install your driver into /lib/modules/$(uname -r)/extra
$ sudo depmod -a # Rebuild the dependency files
After this step, search for the string corresponding to your module in the dependency files, and it should be there! From this moment on, whenever you insert the mouse(or from boot itself) your driver will be loaded, instead of the original.
Once your are done playing with your driver, you may copy back the original usbhid file to its original destination and rebuild the dependency files (sudo depmod -a)
Now I also see that you are trying to use vendor and device id to match your device, in which case, the driver would work only for your mouse. The recommended way is to use class ids, which makes your driver work for any usb mouse.
2) I also read about USB core drivers and USB device drivers. So these HID drivers are core drivers or device drivers?
usbhid is basically a "device driver". The classification of drivers could be briefed out as : core drivers, host controller drivers and device drivers :
Device Drivers : This is the software used to control the devices. For example usb mouse, pci based ethernet card, usb pendrive, i2c based accelerometer.
Host Controller Drivers : This is the software written to control the bus controller. For example USB Host Controllers(EHCI, UHCI, OHCI, etc.), PCI Host Controller, I2C Masters, etc.
Core Drivers : These actually glues up the above discussed drivers. Examples are USB core, PCI core, etc. Core drivers provides helper routines(APIs) such that the device and host-controller driver could make use of them(concept of module stacking!). These are the ones, which bind the correct device to its driver. There are many other services provided by the core drivers.
Example code for USB Device Driver :
http://lxr.free-electrons.com/source/drivers/hid/usbhid/usbmouse.c
You may find the USB Host Controller Drivers under :
http://lxr.free-electrons.com/source/drivers/usb/host/
USB Core resides here : http://lxr.free-electrons.com/source/drivers/usb/core/
I think this also answers your third question!
Hope this helped.
The device driver is usbhid.
To prevent it from attaching to your device, add a HID_QUIRK_IGNORE entry to drivers/hid/usbhid/hid-quirks.c, or use the quirks parameter of the usbhid module.
I have a temperature sensor, which is connected using an USB-I2C adapter (http://www.robot-electronics.co.uk/htm/usb_i2c_tech.htm)
I attached this device to my linux computer (suse10).
I typed dmesg and saw
usb 3-3: new full speed USB device using ohci_hcd and address 10
usb 3-3: new device found, idVendor=0403, idProduct=6001
usb 3-3: new device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-3: Product: FT232R USB UART
usb 3-3: Manufacturer: FTDI
usb 3-3: SerialNumber: A7007K93
usb 3-3: configuration #1 chosen from 1 choice
ftdi_sio 3-3:1.0: FTDI USB Serial Device converter detected
drivers/usb/serial/ftdi_sio.c: Detected FT232BM
usb 3-3: FTDI USB Serial Device converter now attached to ttyUSB0
But I have no idea how to read the current temperature.
updated 1: Actually the I2C bus can attach up to 127 sensors. But I have no idea how to list the addresses of available sensors.
Can anybody give me some hints? Thanks in advance
Your adapter allows you to send I2C commands over a virtual serial port. A serial port has been created for you. You need to open it and send commands to it. The commands are specific to the device you are connected to. See the example in the link you provided to get an idea.
It is hard to give you correct instructions without a datasheet. Most probably your device will use one byte address and the read procedure is as follows:
[I2C_AD1] [Device I2C address + Read bit] [Device Address register] [Number of bytes to read]
0x55 0xXX 0x00 0x01
You need to send 4 bytes to the serial port. The first one instructs the USB to I2C converter to send a read command. The second one is the address of the device attached to the I2C bus. I2C devices use 7-bit addresses (0-127). Usually these are given with one bit shifted at the left. Therefore you need to scan these addresses (iterate from 0 to 127, shift left one bit, set bit0 to 1):
([0x00 - 0x7F] << 1) | 1
Since we don't have a datasheet I can't tell anything about the last two bytes. You could try to use dummy values. If a device is attached to the scanned I2C address, it should reply with a NACK to an attempt to read a non-existing register. Read commands sent to an I2C address that doesn't correspond to an actual device should be ignored.