USB device detection - Windows & Linux (FT232R) - linux

How can I enumerate and identify (get pid, vid and serial) FT232R chips in windows and linux. I need to:
1. at start of program enumerate already plugged devices
2. detect plugging of usb device
3. get PID, VID, Serial
And I need to do that in windows and linux. I know there is libusb for windows as well as for linux, but I don't have that much experience with USB. Code example would be best.

You should use SetupAPIs in Windows for getting device information like hardware id(contains vid and pid both) and to detect the plugging/unplugging see example in this link
Registering for Device Notification
To use SetupAPI you can use below code as reference and add/modify according to your requirement.
#include "stdafx.h"
#include <stdlib.h>
#include <Windows.h>
// Link to setapi.lib
#include <setupapi.h>
void GetDeviceInfo()
{
GUID gUSBGuid;
DWORD ClassGuidListSize = 1;
DWORD RequiredSize = NULL;
//if device shown under "USB" node in Devmgr, else see inf for classname
BOOL bres = SetupDiClassGuidsFromName((PCTSTR)"USB",
&gUSBGuid,//GUID will get populated
ClassGuidListSize,
&RequiredSize);
HDEVINFO hDevInfo = SetupDiGetClassDevs(&gUSBGuid,NULL,NULL,DIGCF_PRESENT);
if (INVALID_HANDLE_VALUE != hDevInfo)
{
BOOL bResult = FALSE;
SP_DEVICE_INTERFACE_DATA tDeviceInterfaceData;
tDeviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
for (int nMemberIndex = 0; TRUE ; nMemberIndex++)
{
SP_DEVINFO_DATA tSpDevInfoData;
tSpDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
//Get the tSpDevInfoData for the instance ID
bResult = SetupDiEnumDeviceInfo(hDevInfo,nMemberIndex,&tSpDevInfoData);
if(bResult)
{
TCHAR *szHardwareId = new TCHAR[128] ;
DWORD dwtype = REG_SZ;
SetupDiGetDeviceRegistryProperty(hDevInfo,&tSpDevInfoData,SPDRP_HARDWAREID
,&dwtype,(PBYTE szHardwareId,256,NULL);
//code to process szHardwareId
delete szHardwareId;
break;
}
}
}
}
I dont have idea for Linux..:(
Hope this helps..

Related

Change remote device name and class via HCI

I have a bluetooth audio interface which I want to change the name and the CoD (Class of Device) parameter. I have tried doing this using hcitool on Ubuntu, with: sudo hcitool cmd 0x03 0x0024 0x260420 which is supposed to set the CoD to 0x260420 (it's currently 0x260404), but I've had no luck. From what I now understand, I take id that you cannot use hcitool on a Linux computer to send cmd commands to a bluetooth device connected to that computer via bluetooth. Is there a way to achieve this?
Is it at all possible to change a bluetooth devices' configuration remotely in any way?
You can try it with a small C script. We will use these two methods you can find in the hci_lib.h header file.
int hci_read_class_of_dev(int dd, uint8_t *cls, int to);
int hci_write_class_of_dev(int dd, uint32_t cls, int to);
Be aware that a Class of Device (CoD) has strict requirements you can find in the official Bluetooth documentation (here). That's why you need sudo to execute.
// Simple program to read and write Class of Device.
// To compile: `gcc -o rw_cod rw_cod.c -lbluetooth`
// To install lbluetooth: `apt-get install libbluetooth-dev`
// Execute with `sudo ./rw_cod`
// Note the original CoD first because it has strict rules, you might need to write it back later.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // for close()
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
int main(void){
int dd = hci_open_dev(hci_devid("DC:A6:32:E4:9C:05"));
int timeout = 1000;
uint8_t cls[3] = {0};
int class;
int ret;
uint32_t new_class = 0x260404;
// Read CoD
ret = hci_read_class_of_dev(dd, cls, timeout);
class = cls[0] | cls[1] << 8 | cls[2] << 16;
printf("Class of Device = 0x%06x [%d]\n", class, ret);
// Set CoD
ret = hci_write_class_of_dev(dd, new_class, 2000);
printf("Required new Class of Device = 0x%06x [%d]\n", new_class, ret);
// Check read CoD
ret = hci_read_class_of_dev(dd, cls, timeout);
class = cls[0] | cls[1] << 8 | cls[2] << 16;
printf("Actual new Class of Device = 0x%06x [%d]\n", class, ret);
close(dd);
return 0;
}
Console returns:
pi#raspberrypi:~/Work_Bluetooth $ sudo ./rw_cod
Class of Device = 0x260404 [0]
Required new Class of Device = 0x260420 [0]
Actual new Class of Device = 0x260420 [0]
pi#raspberrypi:~/Work_Bluetooth $

I cannot send data to my Arduino through usb serial connection

So, I have an arduino uno R3 SMD edition and I want to send commands to it while it's running. It has an adafruit v2 motor shield connected to it, which is powered separately from the arduino. The arduino is connected to my laptop by a usb cable.
Now, the motor shield works and I can send code to the arduino to make it do things. I can't get the arduino to receive anything I send to it while it's running from the serial connection though. I can print to the monitor in the arduino ide from arduino code though. I'm on debian linux stretch btw. My arduino ide is from the debian repos.
Here is all the code I'm trying to use:
Arduino Code
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);
void setup()
{
Serial.begin(115200);
AFMS.begin();
myMotor->setSpeed(300);
}
char input;
int dir;
void loop()
{
dir = 0;
if (Serial.available() > 0) {
input = Serial.read();
Serial.print(input);
if (input == 1) {
dir = FORWARD;
}
if (input == 2) {
dir = BACKWARD;
}
}
if (dir != 0) {
myMotor->step(360, dir, DOUBLE);
delay(1000);
}
}
Controller Code on Laptop
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char **argv)
{
FILE *arduino;
int c;
arduino = fopen("/dev/ttyACM0", "w");
if (arduino == NULL) {
fprintf(stdout, "NOOOOOOOOOOOO\n");
}
while (1) {
c = fgetc(stdin);
if (c == 'f') {
fprintf(arduino, "%d", 1);
}
if (c == 'b') {
fprintf(arduino, "%d", 2);
}
fflush(arduino);
if (c == 'q') {
break;
}
}
return 0;
}
I'm pretty sure this isn't a permissions problem, I've run the controller code from root and the tty device opens fine. Also, I've tried both 9600 and 115200 for my baud rate, but no dice. Does anyone have an idea? From googling it really seems like this is all anyone else is doing.
Your controller is sending characters '1' and '2'. Your Arduino is checking for character codes 1 and 2 - in other words, the characters CtrlA and CtrlB. You can make the change at either end, they just need to match.

Windows application using libusb: runtime error due to mutex lock

I am trying to establish communication between a laptop and an embedded board over USB. USB driver for board has been installed and it has been detected in Windows device manager. Now I am developing code in Visual Studio 2013 (Win32 Console Application) using libusb.
The libusb_init() function does not return an error however when I try to open the device with libusb_open_device_with_vid_pid(), execution breaks at function usbi_mutex_init() in the threads_windows.c file of the libusb library. This file contains the source for "libusb synchronization on Microsoft Windows".
I also tried to call function libusb_get_device_list() but get the same error. Could you please suggest a solution?
main.cpp from my application source code -->
#include <iostream>
#include "libusb.h"
using namespace std;
int main()
{
int init_status = 0;
libusb_context *context = NULL;
libusb_device_handle *device;
init_status = libusb_init(&context);
if (init_status<0)
{
cout << "could not initialize";
return -1;
}
device = libusb_open_device_with_vid_pid(NULL, 0x0483, 0x5750); //execution breaks here
if (device == NULL)
{
cout << "could not open device";
return -1;
}
else
{
cout << "Device opened successfukky";
}
return 0;
}
threads_windows.c from libusb source code -->
int usbi_mutex_lock(usbi_mutex_t *mutex) {
DWORD result;
if(!mutex) return ((errno=EINVAL));
result = WaitForSingleObject(*mutex, INFINITE); //execution breaks here
if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
return 0; // acquired (ToDo: check that abandoned is ok)
return ((errno=EINVAL)); // don't know how this would happen
// so don't know proper errno
}
Looks to me like you get a specific, non-default context with your libusb_init() but when you use libusb_open_device_with_vid_pid() you are pass NULL which means to use the default context rather than the context created by the libusb_init().
You may just want to use the default context if it is a single device and you only need a single session. The documentation indicates that there are "limitations" with libusb_open_device_with_vid_pid() and it is not intended for anything other than test applications. I assume this is because in real applications there may be multiple devices and this convenience function just takes the first one matching the arguments. However the issue you are seeing is probably related to the context.
For a one off type of specific project your code would look something like:
#include <iostream>
#include "libusb.h"
using namespace std;
int main()
{
int init_status = 0;
libusb_device_handle *device;
// specify NULL for the context address so that libusb_init will use default content.
// this means that any libusb function with a context argument will be called with NULL.
init_status = libusb_init (NULL);
if (init_status < 0)
{
cout << "could not initialize";
return -1;
}
// open the first device found in the device list with this vendor id and product id
// for a real application in a multi-device environment we would need to
// iterate through the various devices using libusb_get_device_list() to get
// the list of devices then using libusb_get_device_descriptor() to iterate
// through the list to find the device we want. also need libusb_free_device_list ()
// after finishing with the list. lots of work for a simple one off project
device = libusb_open_device_with_vid_pid (NULL, 0x0483, 0x5750);
if (device == NULL)
{
cout << "could not open device";
return -1;
} else {
cout << "Device opened successfully";
}
return 0;
}

Configure PIC port for input and output

I'm trying to use two pins of Port A on my PIC18F4620, with one as an output and the other as an input. I've written a simple program that should do this. However, when I debug the program on my board, the output doesn't change according to the input.
I understand why it would be necessary to change the pin configuration every time if I was only using one pin, but the fact that I'm using two different pins (A0 and A1) has me confused. Also, the output does change when I use two different ports (ex. A0 and D1).
Am I missing something, or is this a limitation I have to work around in my design?
Here is the code:
#include <xc.h>
#include "config.h"
void main(void){
TRISAbits.RA0 = 1;
TRISAbits.RA1 = 0;
while(1){
if(PORTAbits.RA0 == 1){
LATAbits.LA1 = 0;
}
else{
LATAbits.LA1 = 1;
}
}
}
Port A on the PIC18F4620 is multiplexed with the analog/digital converter, so you have to configure some settings before being able to use Port A as digital I/O. Take a look at page 91 of the datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/39626e.pdf
And change your code to the following:
#include <xc.h>
#include "config.h"
void main(void){
ADCON1 = 0x0F; // Configure A/D for digital input/output on all pins
CMCON = 0x07; // Configure comparator for digital input/output
TRISAbits.RA0 = 1;
TRISAbits.RA1 = 0;
while(1){
if(PORTAbits.RA0 == 1){
LATAbits.LA1 = 0;
}
else{
LATAbits.LA1 = 1;
}
}
}

Finding all the devices I can use to play PCM with ALSA

I use ALSA to play PCM samples. I open the PCM stream with this function:
int snd_pcm_open(snd_pcm_t** pcmp,
const char* name,
snd_pcm_stream_t stream,
int mode);
I'm currently using "default" as the name parameter. I would like to be able to choose other devices. What I cannot understand is how I can determine what are the names of the other available devices.
I attached a USB microphone to my system and aplay and amixer seems to detect the new device. How do I determine the name of that device? Is there any ALSA function to get a list of available devices with their respective names?
I think you can use snd_device_name_hint for enumerating devices.
Here is an example. Beware that I haven't compiled it !
char **hints;
/* Enumerate sound devices */
int err = snd_device_name_hint(-1, "pcm", (void***)&hints);
if (err != 0)
return;//Error! Just return
char** n = hints;
while (*n != NULL) {
char *name = snd_device_name_get_hint(*n, "NAME");
if (name != NULL && 0 != strcmp("null", name)) {
//Copy name to another buffer and then free it
free(name);
}
n++;
}//End of while
//Free hint buffer too
snd_device_name_free_hint((void**)hints);
It was my first requirements to a linux/unix projects where I need to know about all of the available audio devices capability and name. Then I need to use these devices to capture and plaback the audio. What I have done is pretty simple. There is a linux/unix command which is used to find the devices through alsa utility in linux.
It is:
aplay -l
Now what I did is just make a programme to give the out as like as this by alsa.
For everyone's help I have made a (.so) library and a sample Application demonstrating the use of this library in c++.
The output of my library is like-
[root#~]# ./IdeaAudioEngineTest
HDA Intel plughw:0,0
HDA Intel plughw:0,2
USB Audio Device plughw:1,0
This library can also capture and playback the real-time audio data.
It is available with documentation in IdeaAudio library with Duplex Alsa Audio
Just for grins, your program reformatted:
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <alsa/asoundlib.h>
void listdev(char *devname)
{
char** hints;
int err;
char** n;
char* name;
char* desc;
char* ioid;
/* Enumerate sound devices */
err = snd_device_name_hint(-1, devname, (void***)&hints);
if (err != 0) {
fprintf(stderr, "*** Cannot get device names\n");
exit(1);
}
n = hints;
while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME");
desc = snd_device_name_get_hint(*n, "DESC");
ioid = snd_device_name_get_hint(*n, "IOID");
printf("Name of device: %s\n", name);
printf("Description of device: %s\n", desc);
printf("I/O type of device: %s\n", ioid);
printf("\n");
if (name && strcmp("null", name)) free(name);
if (desc && strcmp("null", desc)) free(desc);
if (ioid && strcmp("null", ioid)) free(ioid);
n++;
}
//Free hint buffer too
snd_device_name_free_hint((void**)hints);
}
int main(void)
{
printf("PCM devices:\n");
printf("\n");
listdev("pcm");
printf("MIDI devices:\n");
printf("\n");
listdev("rawmidi");
return 0;
}

Resources