know a usb device's endpoint - endpoint

Is there a bash command, a program or a libusb function (although I did not find one) which indicates me what are the OUT or IN endpoints of a usb device ?
For example, bNumEndpoints of libusb_interface_descriptor (from libusb1.0 library) shows me my usb drive has 3 endpoints, but how can I know what is their idnumber ?

After you have claimed the device, run this (where $ represents the terminal entry point):
$ sudo lsusb -v -d 16c0:05df
Where 16c0:05df are your vendor and product ids separated by a colon. (If you don't know these, type lsusb and figure out which device is yours by unplugging and re-running lsusb)
If you get confused use the lsusb man page:
http://linux.die.net/man/8/lsusb
Then once your description comes up, find the line labeled bEndpointAddress and the hex code following will be the endpoint for that specific Report.

I finally found the answer in lubusb-1.0. In was actually not a function, but a struct field :
uint8_t libusb_endpoint_descriptor::bEndpointAddress
The address of the endpoint described by this descriptor.
Bits 0:3 are the endpoint number. Bits 4:6 are reserved. Bit 7
indicates direction, see libusb_endpoint_direction.
For each interface for the usb drive, I just had to write these lines to display the available endpoints :
cout<<"Number of endpoints: "<<(int)interdesc->bNumEndpoints<<endl;
for(int k=0; k<(int)interdesc->bNumEndpoints; k++) {
epdesc = &interdesc->endpoint[k];
cout<<"Descriptor Type: "<<(int)epdesc->bDescriptorType<<endl;
cout<<"EP Address: "<<(int)epdesc->bEndpointAddress<<endl;
}
Where epdesc is the libusb_endpoint_descriptor and interdesc is the libusb_interface_descriptor.

Related

Can't open a serial port in g++ on Ubuntu

I am trying to run the sample programs that came with a development lidar unit (RPLIDAR A1M8 360 Degree Laser Scanner Kit). The sample code for a Linux target compiles without error using g++
(Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0 however when I run it, it stops with the message 'Error, cannot bind to the specified serial port /dev/ttyUSB0'. Using gdb I can trace the code down to the serial port open call to __libc_open64 where I don't have source anymore...
__libc_open64 (file=0x5555557832a9 "/dev/ttyUSB0", oflag=2306) at ../sysdeps/unix/sysv/linux/open64.c:36}
36 ../sysdeps/unix/sysv/linux/open64.c: No such file or directory.
Here is what I tried so far to eliminate obvious failure modes:
The serial port, a USB-to-serial converter on ttyUSB0, works just fine from Putty (115200, 8, none, 1, software flow control only). I connect it to a Raspberry Pi as the console to get a large amount of data without issue and can bidirectionally interact with the console. Therefore I conclude the port and converter work fine
The section of code that calls __libc_open64 is...
bool raw_serial::open(const char * portname, uint32_t baudrate, uint32_t flags)
{
if (isOpened()) close();
serial_fd = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
I looked up the constants that are ORed together and hard coded the value (04403) just in case there was some issue with the version of the header files. Oddly the value is off by 1 from the oflag value in the gdb line. Compiled and ran it, no difference
I verified the call to ::open returned -1 which is treated as a failure in the code immediately after
I can see in dmesg that ttyUSB0 is open and available
I am not a c++ guy. This looks to me like an issue with the g++ __libc_open64 code but that also seems very unlikely. I don't know where to go next. Any advice would be greatly appreciated.
The first comments received pointed to permissions. I chmoded /dev/ttyUSB0 wide open before starting this exercise.
I ran strace and see the line...
openat(AT_FDCWD, "/dev/ttyUSB0", O_ACCMODE|O_NOCTTY|O_NONBLOCK) = -1 ENOENT (No such file or directory)
Well, that's embarrassing! It returns Permission Denied! Yes, I chmoded permissions wide open, then promptly forgot that being a USB device, it goes away and gets redefined when I unplug/plug it in again. Thank you for your help!
The prediction that strace would show "Permission denied" was correct. I was forgetting this is not a fixed serial port but rather a USB-to-serial converter. Even though I chmoded the permissions and verified it use with Putty, I forgot that as soon as I rebooted, or unplugged the USB, the /dev/ttyUSB0 device goes away and is recreated again when I rebooted or plugged it in, requiring that I set the permissions again.

Get inode for lookup in /proc/net/udp

I am trying to programmatically track the amount of data in my receive buffer. I am receiving UDP data. After doing some research it seems that the only way to do this in Linux is to look at /proc/net/udp. This seems like a good solution until I realized that two applications could be listening to the same multicast group and I need to tell them apart. It seems that I am supposed to do this by determining what my inode is.
I spend some time looking into this and there are suggestions that sockfd_lookup or sock_from_file is the way to go but on my CentOS Linux machine, these functions do not seem to be available.
Can someone please help me to figure out which line in /proc/net/udp belongs to my application?
I started using the ioctl (handle, FIONREAD, &bytesInBuffer) call only to discover that in Linux this only returns the size of the first datagram packet in the buffer.
Google seems to suggest that the sockfd_lookup call can be used to get the inode but a grep in my /usr/local/include/ does not return these functions.
My linux/net.h seems pretty bare-bone compared to some I can find on google which includes structs like "socket" which has the sock member which I believe has the inode information. My linux/net.h on CentOs only is 58 lines long and has only a few #defines and an enum.
after a bit of fiddling I noticed that readlink("/proc/self/fd/$fd") (under Linux 5.3) gives me something like:
socket:[3753088]
back. I can parse this and use the resulting digits to look up the relevant line in /proc/net/udp:
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
2867: 00000000:0BB8 00000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 3753088 2 000000003ae8e911 0
that said, I don't understand why you'd want to do this, but never mind!
I'm also not sure why you don't just look up by sock&peer name, which might be easier

How do I programatically remove a flash drive based on its device node name?

I have a Linux system with multiple USB flash drives plugged in, as /dev/sda1, /dev/sdb1, etc. I need to eject one of these from within my program -- something like EjectDrive("/dev/sdb1"); I then may need to programmatically re-insert the drive.
I know I can do this from the command line if I know the USB bus, port and device number. e.g. echo '2-1.3' > /sys/bus/usb/drivers/usb/unbind and then echo '2-1.3' > /sys/bus/usb/drivers/usb/bind
I'm not sure how to do this from C++, and be 100% sure I am using the correct bus, port and device for the specified drive.
This is an embedded platform with BusyBox v1.22.1, so udev is not available to me, and lsusb returns minimal information.
Yes it can be done using libusb (follow this link for libusb usage with C++). Now a few things to keep in mind -
1 - What is the device address? (You can get this using libusb API)
libusb_get_device_list (libusb_context *ctx, libusb_device ***list)
libusb_get_device_address (libusb_device *dev)
libusb_get_port_number (libusb_device *dev)
2 - Is the device connected to the root hub port or to a hub port? (This can be done by reading the parent device of the /dev/sdb1 or sda1)
libusb_get_parent (libusb_device *dev)
3 - If its connected to a hub, then do a control transfer to "clear" PORT_POWER feature of that port. That will turn off the port and the device will be disconnected. You can "set" PORT_POWER feature to turn on the port and the device will be connected again. Remember that you will not get any disconnect event which is as per the spec. (EHCI or XHCI)
int libusb_control_transfer ( libusb_device_handle * dev_handle,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
unsigned char * data,
uint16_t wLength,
unsigned int timeout
)
4 - If the device is connected to the root hub port directly, then please check if libusb supports clearing root hub port power. I am not sure about this. This also depends on the Host controller driver stack.
Please follow the link I mentioned at the top for example usage of these API's.

C Program to find UP and DOWN machines.?

Suppose I have a scenario like below :
There are about 225 Computers having the following range of IP addresses and hostnames:-
PC-LAB IP ADDRESS RANGE HOSTNAME RANGE
PC-LAB1 10.11.2.01 - 10.11.2.30 ccl1pc01 - ccl1pc30
PC-LAB2 10.11.3.01 - 10.11.3.30 ccl2pc01 - ccl2pc30
PC-LAB3 10.11.4.01 - 10.11.4.45 ccl3pc01 - ccl3pc45
PC-LAB4 10.11.5.01 - 10.11.5.50 ccl4pc01 - ccl4pc50
PC-LAB5 10.13.6.01 - 10.13.6.65 ccl5pc01 – ccl5pc65
I want to write a program (in C / C++) that will take the above IP address and hostname ranges as input and create two separate files, one with 225 entries of IP
addresses and another with 225 entries of hostnames..
Then the program will figure out which of these machines are up and which are down and then create two files one containing
hostname and IP addresses of the systems which are UP and another which are DOWN.
E.g.
FILE1.down
Hostname IP address
ccl1pc10 10.8.2.10
ccl5pc25 10.11.5.25
Note : If any ubuntu command simplifies this work..we can use that in the program for sure..!!
Look at fping
Run this command, sit back and relax:
fping ccl{1..6}pc{01..60}
this will print a list of
All hosts that have a DNS name/IP record and are up
All hosts that have a DNS name/IP record but are down
All hosts that are not in the DNS (I guess you can ignore these)
Regards
Check out Nmap. You might need to create a small wrapper to handle the input and output in the format you want, but it should do exactly what you need.
Is this homework, ie do you have to do it programmatically in C?
Otherwise there a dozen of already existing monitoring frameworks, with several already in Ubuntu: munin, nagios, zabbix, ...

How to read a multi-session DVD disk size in Windows?

Trying to read the sizes of disks that were created in multiple sessions using GetDiskFreeSpaceEx() gives the size of the last session only. How do I read correctly the number and sizes of all sessions in C/C++?
Thanks.
You might want to look at the DeviceIoControl API function. See here for control codes. Here is a code example that retrieves the size of a CD disk. Substitute
CreateFile(TEXT("\\\\.\\PhysicalDrive0")
for e.g.
CreateFile(TEXT("\\\\.\\F:") /* Drive is F: */
if you wish.
Note: The page says that DeviceIoControl can be used to "retrieve information about a floppy disk drive, hard disk drive, tape drive, or CD-ROM drive", but I have also tested it on a DVD, and it seemed to work perfectly. I did not have access to any multisession DVDs to test, so you'll have to test if that works yourself. If it doesn't work, I'd try some of the other control codes, at least IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, IOCTL_DISK_GET_LENGTH_INFO and IOCTL_DISK_GET_PARTITION_INFO_EX.
If all fails with DeviceIoControl, you could possibly make use of the Windows Image Mastering API (IMAPI). You'll need v2 of the API (included with Vista & later, can be added to XP & 2003 too, see here: What's new in IMAPIv2) for DVD support. This API is primarily for CD burning, but does perhaps contain some functionality for retrieving disk size, I'd find it weird if it didn't. Particularly, this example seems to be interesting. I do not know if this one works for multisession disks either, but since it can create them, I guess it's likely.
Here are some resources for IMAPI:
MSDN - IMAPI
MSDN - IMAPI interfaces
MSDN - Creating multisession disks with IMAPI (note: example with VB, not C or C++)
Hey I got at least 2 solutions for you:
1) Download dvd+rw-mediainfo.exe from http://fy.chalmers.se/~appro/linux/DVD+RW/tools/win32/, it's a tool that reads info about your disc. Then just make a system call from your app and parse the results. Here's example output:
D:\Downloads>"dvd+rw-mediainfo.exe" f:
INQUIRY: [HL-DT-ST][DVDRAM GT30N ][1.01]
GET [CURRENT] CONFIGURATION:
Mounted Media: 10h, DVD-ROM
Current Write Speed: 1.0x1385=1385KB/s
Write Speed #0: 8.0x1385=11080KB/s
Write Speed #1: 4.0x1385=5540KB/s
Write Speed #2: 2.0x1385=2770KB/s
Write Speed #3: 1.0x1385=1385KB/s
Speed Descriptor#0: 00/2292991 R#8.0x1385=11080KB/s W#8.0x1385=11080KB/s
READ DVD STRUCTURE[#0h]:
Media Book Type: 01h, DVD-ROM book [revision 1]
Legacy lead-out at: 2292992*2KB=4696047616
READ DISC INFORMATION:
Disc status: complete
Number of Sessions: 1
State of Last Session: complete
Number of Tracks: 1
READ TRACK INFORMATION[#1]:
Track State: complete
Track Start Address: 0*2KB
Free Blocks: 0*2KB
Track Size: 2292992*2KB
Last Recorded Address: 2292991*2KB
FABRICATED TOC:
Track#1 : 17#0
Track#AA : 17#2292992
Multi-session Info: #1#0
READ CAPACITY: 2292992*2048=4696047616
2) Investigate mciSendString from [DllImport("winmm.dll", EntryPoint = "mciSendStringA", CharSet = CharSet.Ansi)], I suspect you can send some command and get the desired results.
PS: of course you may download dvd+rw-mediainfo.exe sources from here and investigate further, I am just giving you ideas to think of.
UPDATE
Link to source code updated, thanks #oystein
There are many way to do this since the DVD drives have several interfaces for this due to legacy and backward-compatibility issues.
You could send an IOCTL_SCSI_PASSTHROUGH_DIRECT command to the DVD-drive ( the physicaldevice handle for it). With it you issue a SCSI commands that will be answered by the drive. You can read session information, disk information disk capcity and more.
I believe that dvd+rw-mediainfo.exe issues these.
Unfortunatly, the interface is a bit tricky and obscure, since it is a command within a command. Th passthrough has a byte buffer you will have to fill in yourself with the command structure.
Or you can call IOCTL_CDROM_READ_TOC_EX:
http://www.osronline.com/ddkx/storage/k306_2cs2.htm
I also believe that the exact set of the IOCTL / commands that will work depends on on the drive and its firmaware.
Older drives will not support the newr interfaces and some of the newer drives will not support legacy interfaces.
Thus, some of the libraries & tools might use one or more of these interfaces.
Accseeing the older sessons is all quite messy, really, since most OS will not care about them, only the most recent ones.