I am writing the data to /dev/ttyO3 in my application .The write is succeeded but not visible int he cat /dev/ttyO3.
ttyO3 is the device name for the uart4 instance of omap4460 pandaboard.
Edit 1:But some pulses are showing up when I probe through CRO.
How should I change my code to enable the software loop back?ie(I want the same pulse to be seen at rx pin without shorting Tx-Rx)
#define DEVICE "/dev/ttyO3"
int main()
{
int fd;
int write_fd1;
struct termios options;
fd = open(DEVICE,O_RDWR);
if(fd < 0)
printf("unable to open the device\n");
else
printf("device opened %d \n",fd);
tcgetattr(fd,&options);
cfsetospeed(&options,B300);
cfsetispeed(&options,B300);
tcsetattr(fd,TCSANOW,&options);
tcgetattr(fd,&options);
if((cfgetospeed(&options) != B300) || (cfgetispeed(&options)!= B300));
{
printf("Baud rate not set");
}
while(1)
{
write_fd1 = write(fd,"a",2) ;
printf("write_fd %d \n",write_fd1);
}
close(fd);
return 0;
}
Related
I have been writing some code to access I²C based on the following (which works).
I was attempting to implement something more general, and include error checking.
All the code examples I have seen include similar code to:-
if(ioctl(file, I2C_SLAVE, 0x68) < 0){
perror("Failed to connect to the sensor\n");
return 1;
}
If I use a nonexistent address the code fails, but there is no error.
Can anyone suggest what I am doing wrong?
/** Simple I2C example to read the time from a DS3231 module
* Written by Derek Molloy for the book "Exploring Raspberry Pi" */
#include<stdio.h>
#include<unistd.h> // IB 2022-6-29
#include<fcntl.h>
#include<sys/ioctl.h>
#include<linux/i2c.h>
#include<linux/i2c-dev.h>
#define BUFFER_SIZE 19
// the time is in the registers in decimal form
int bcdToDec(char b) { return (b/16)*10 + (b%16); }
int main(){
int file;
printf("Starting the DS3231 test application\n");
if((file=open("/dev/i2c-1", O_RDWR)) < 0){
perror("failed to open the bus\n");
return 1;
}
if(ioctl(file, I2C_SLAVE, 0x68) < 0){
perror("Failed to connect to the sensor\n");
return 1;
}
char writeBuffer[1] = {0x00};
if(write(file, writeBuffer, 1)!=1){
perror("Failed to reset the read address\n");
return 1;
}
char buf[BUFFER_SIZE];
if(read(file, buf, BUFFER_SIZE)!=BUFFER_SIZE){
perror("Failed to read in the buffer\n");
return 1;
}
printf("The RTC time is %02d:%02d:%02d\n", bcdToDec(buf[2]),
bcdToDec(buf[1]), bcdToDec(buf[0]));
float temperature = buf[0x11] + ((buf[0x12]>>6)*0.25);
printf("The temperature is %.2f°C\n", temperature);
close(file);
return 0;
}
I am working an a serial communication project where two applications server and client will send to each other messages.
For example client send a string command server receives this and after processing response with a value. One example of that is : client AT+REG1 server value.
If client sends the message AT+REG1=value then the server must inform his system that the value of current register1 which client needs has changed.
In order to achieve this I keep a stack where at the beginning of the program I am pushing into stack a default value for register1 and if server detect this message AT+REG1= pops the old value and push the new into stack.
Currently if client sends the message AT+REG1, server must response with the new value and not with the old one that I push it by default in the beginning. All the stuff in pop push and generally at stack operations are going right.
My problem is, when I start with AT+REG1, client receives the default value but when I start with AT+REG1=5 (server must change the value from the stack and replace it with the new "5") I am not getting any response. At this point I have to mention that in terminal I am seeing the changes in the stack (with printf for example at AT+REG1=5 , he pops the old and push the new) but I cannot have the result.
The problem that I noticed when trying to print the value that pops out from stack terminal says that it is of type int DESPITE that am not using or creating integers, all the values are in char form.
SERVER.C
//data structures
typedef enum operation{
insert,
read_reg,
info
}Operation;
typedef struct request{
Operation operation;
char old_value1[SIZE];
char old_value2[SIZE];
int flag; //flag to know which register is
int counter1;
int counter2;
}Request;
Request c1;
Request c2;
//Prototype Functions
Request *parse_request(char *buffer);
void process_request(int fd);
int isEmpty(char *stack);
int isFull(char *stack);
void push(char num,char *stack);
char pop(char *stack);
char *stack1,*stack2;
int top1=-1,top2=-1;
char t1,t2;
int main(int argc , char * argv[]){
int fd; //file descriptor of the port
char *port; // port name
struct termios tty; //connection manager
stack1=(char*)malloc(STACK_SIZE*sizeof(char));
stack2=(char*)malloc(STACK_SIZE*sizeof(char));
if(argc < 1){
printf("You have to enter a specific tty file to open\n");
exit(1);
}
//Opening port .
port =argv[1];
fd=open(port,O_RDWR|O_NOCTTY| O_NONBLOCK);
if(fd==-1){
perror(port);
exit(1);
}
printf("[+] port opened succesfully!\n");
if(tcgetattr(fd,&tty)!=0){
printf("tcgetattr : %s \n",strerror(errno));
}
//BAUD RATE SETTINGS (read and write speed)
cfsetospeed(&tty,B115200);
cfsetispeed(&tty,B115200);
cfmakeraw(&tty);
// Settings for control modes
tty.c_cflag &= ~PARENB; // Clear the parity bit for the serial communication
tty.c_cflag &= ~CSTOPB; // Using only one stop bit in this communication
tty.c_cflag |= CS8; // Set 8 bits per byte in transmittion
tty.c_cflag &= ~CRTSCTS; // Disable the RTS/CTS flow control
tty.c_cflag |= CREAD | CLOCAL; // Setting clocal up ("1") .Usefull for reading data
tty.c_lflag &= ~ICANON; // Setting on the non-canonical mode
tty.c_lflag &= ~ISIG; // Disable the INTR - QUIT - SUSP characters
tty.c_iflag &= ~IGNPAR;
//Blocking read operation and setting maximum timeout 1 second
tty.c_cc[VTIME]=1;
tty.c_cc[VMIN] =0;
//Setting the options
tcsetattr(fd,TCSANOW,&tty);
//setting first values for each register!
push('0',stack1);
push('1',stack2);
c1.counter1=0;
c2.counter2=0;
printf("[+] Connection starting !\n");
while(1){
process_request(fd);
}
}
Request *parse_request(char *buffer){
char *token=NULL;
char *take[3];
int i=0,num;
Request *rep=NULL;
if(!buffer)
return NULL;
rep=(Request*)malloc(sizeof(Request));
memset(rep->old_value1,0,SIZE);
memset(rep->old_value2,0,SIZE);
if(strcmp(buffer,"AT+REG1")==0) {
rep->operation=read_reg;
rep->flag=1;
}else if(strcmp(buffer,"AT+REG2")==0){
rep->operation=read_reg;
rep->flag=2;
}else if(strcmp(buffer,"AT+REG2")!=0 || strcmp(buffer,"AT+REG1")!=0){
token=strtok(buffer,"=");
while(token!=NULL){
take[i]=token;
token=strtok(NULL," ");
i++;
}
if(strcmp(take[0],"AT+REG1")==0 && strcmp(take[1],"?")==0){
rep->operation=info;
rep->flag=1;
}else if(strcmp(take[0],"AT+REG2")==0 && strcmp(take[1],"?")==0){
rep->operation=info;
rep->flag=2;
}else if(strcmp(take[0],"AT+REG1")==0 && take[1]!=NULL){
rep->operation=insert;
rep->flag=1;
//Scanning for errors
if(atoi(take[1])>16535 || atoi(take[1])<0)
return rep=NULL;
char rev;
if(!isEmpty(stack1)){
//take the old value from the stack and save it
rep->old_value1[c1.counter1]=pop(stack1);
c1.counter1++;
int num=atoi(take[1]);
rev= num;
push(rev,stack1);
}else{
//push the new value into the stack
int num=atoi(take[1]);
rev= num;
push(rev,stack1);
}
}else if(strcmp(take[0],"AT+REG2")==0 && take[1]!=NULL){
rep->operation=insert;
rep->flag=2;
//Scanning for errors
if(atoi(take[1])>3 || atoi(take[1])<1)
return rep=NULL;
char rev;
if(!isEmpty(stack2)){
rep->old_value2[c2.counter2]=pop(stack2);
c2.counter2++;
int num=atoi(take[1]);
rev=num;
push(rev,stack2);
}else{
int num=atoi(take[1]);
rev=num;
push(rev,stack2);
}
}else{
free(rep);
return(NULL);
}
}else{
free(rep);
return(NULL);
}
return rep;
}
void process_request(int fd){
fd_set readfd;
int status;
char *str;
char buffer[SIZE];
int read_num=0;
char *str1;
struct flock fl;
struct timeval timeout;
Request *request;
fl.l_type = F_RDLCK; /* read lock */
fl.l_whence = SEEK_SET; /* beginning of file */
fl.l_start = 0; /* offset from l_whence */
fl.l_len = 0; /* length, 0 = to EOF */
fl.l_pid = getpid(); /* PID */
//Clean buffer
memset(buffer,0,SIZE);
FD_ZERO(&readfd);
FD_SET(fd,&readfd);
timeout.tv_sec=100;
timeout.tv_usec=0;
status=select(40,&readfd,NULL,NULL,&timeout);
if(status==0){ //no data is receiving !
printf("Cannot receive data from client\n");
printf("\tTime Out\n");
exit(1);
}
//read from file descriptor
read_num=read(fd,buffer,sizeof(buffer));
if(read_num<0)perror("Error in reading\n");
if(read_num){
fcntl(fd, F_SETLKW, &fl); // set lock
str1=strdup(buffer);
request = parse_request(str1);
if(request){
switch(request->operation){
case info:
if(request->flag==1){
write(fd,"0-16535\n",20);
}else if(request->flag==2){
write(fd,"1|2|3\n",40);
}
break;
case read_reg:
if(request->flag==1){
//HERE IS THE PROBLEM!!!
t1=pop(stack1);
printf("%s\n",t1); // it understand this as int why ?
write(fd,&t1,5);
//---------------
}else if(request->flag==2){
t2=pop(stack2);
write(fd,&t2,sizeof(t2));
}
break;
case insert:
if(request==NULL)
write(fd,"INVINPUT\n",20);
write(fd,"OK\n",5);
break;
default:
printf("Something went wrong\n");
break;
}
if(request)
free(request);
}
}
fl.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &fl); // unset lock
}
int isEmpty(char *stack){
if(stack==stack1){
if(top1==-1)
return 1;
return 0;
}else if(stack==stack2){
if(top2==-1)
return 1;
return 0;
}
}
int isFull(char *stack){
if(stack==stack1){
if(top1==STACK_SIZE)
return 1;
return 0;
}else if(stack==stack2){
if(top2==STACK_SIZE)
return 1;
return 0;
}
}
void push(char num,char *stack){
if(stack==stack1){
if(!isFull(stack1)){
printf("Eisagogh\n");
top1++;
//*(stack+top1)=num;
stack1[top1]=num;
}else{
printf("Error , push at stack1\n");
}
}else if(stack==stack2){
if(!isFull(stack2)){
top2++;
*(stack2+top2)=num;
}else
printf("Error , push at stack2\n");
}
}
char pop(char *stack){
char str_num;
if(stack==stack1){
if(!isEmpty(stack)){
printf("Eksagogh\n");
str_num=*(stack+top1);
top1--;
return str_num;
}else
printf("Error in pop item from stack1\n");
}else if(stack==stack2){
printf("me vlepeis edo ?\n");
if(!isEmpty(stack)){
str_num=*(stack+top2);
top2--;
return str_num;
}else
printf("Error in pop item from stack2\n");
}
}
Running :
CLIENT
AT+REG1=5
writing AT+REG1=5 command
Response:OK
AT+REG1
writing AT+REG1 command
Responce :
SERVER
[+] port opened succesfully!
push //it is the default value that I insert into the stack
[+] Connection starting !
pop // pops out the default value
push // seems that inserting the value 5 that client asked
pop // and now that pop is for writing to serial port in order client reads it (HERE IS THE PROBLEM) this is the point where I mention in the code that I have problem terminal seeing it as integer and not as char , go check this at process_requst function in server above.
If client sends although AT+REG1 he response the default value where server pops out from stack and send it in the point where the problem is . Please if anyone can help i would appreciate.
I am quite new to this stuff, so be aware. I want to read a single char from an arduino. Therefore I have enabled the serial communication on the arduino with a baud rate of 9600 (more than enough for my needs). This following code works - sometimes. Sometimes I read the correct data and sometimes I get some invaid characters. Also there is the problem that if the device is initialized but then the USB is disconnected (for example just pull the cable), this program does not terminate. What am I doing wrong?
int main() {
int fd = open("/dev/ArduinoDeviceName", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0) {
printf("Failed to connect to device!\n");
return EXIT_FAILURE;
}
struct termios SerialPortSettings;
tcgetattr(fd, &SerialPortSettings);
cfsetispeed(&SerialPortSettings,B9600);
cfsetospeed(&SerialPortSettings,B9600);
if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) {
printf("Error while setting attributes \n");
return EXIT_FAILURE;
}
printf("Init done!\n");
printf("read: _%c_", read_next_char(fd));
close(fd);
return EXIT_SUCCESS;
}
EDIT 1:
Now with some additional settings I could achieve to read the correct data values, see code below:
char read_next_char(int fd) {
char buffer[1] = {0};
fcntl(fd, F_SETFL);
switch (read(fd, &buffer, sizeof(buffer))) {
case 1: printf("Read bytes correct!\n"); break;
case 0: printf("Reached EOF\n"); break;
case -1: printf("Error occured while reading!\n"); break;
default: break;
};
return buffer[0];
}
int main() {
int fd = open("/dev/tty.usbmodem14101", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0) {
printf("Failed to connect to device!\n");
return EXIT_FAILURE;
}
struct termios SerialPortSettings;
tcgetattr(fd, &SerialPortSettings);
cfsetispeed(&SerialPortSettings,B9600);
cfsetospeed(&SerialPortSettings,B9600);
SerialPortSettings.c_iflag=0;
SerialPortSettings.c_oflag=0;
SerialPortSettings.c_cflag=CS8|CREAD|CLOCAL;
SerialPortSettings.c_lflag=0;
SerialPortSettings.c_cc[VMIN]=1;
SerialPortSettings.c_cc[VTIME]=5;
if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) {// Set the attributes to the termios structure
printf("Error while setting attributes \n");
return EXIT_FAILURE;
}
printf("Init done!\n");
char read;
while((read = read_next_char(fd)) != 0) {
printf("Correctly read: _%c_", read);
}
close(fd);
return EXIT_SUCCESS;
}
The only thing that sometimes can be annoying is, that the arduino sends some data via serial in a loop with some delay. If the computer connects there are always some data sent, before the arduino resets. How can I achieve that the arduino / serial port gets reset before I read any data?
I'm working on a embedded linux system (yocto based) and I'm trying to simply get a list of the camera USB video devices (webcams) numbers with the related connected usb port from a C program.
I'm able to get the devices list with vendor ID and connected port doing this:
void usbdevs()
{
libusb_device*** list=NULL;
libusb_context *context = NULL;
ssize_t count;
uint8_t port;
char ncameras=0;
libusb_init(&context);
count = libusb_get_device_list(context,&list);
for(int i=0; i < MAX_NUM_CAMS; i++)
usb_dev_list[i]=0;
for (size_t idx = 0; idx < count; ++idx) {
libusb_device *device = list[idx];
struct libusb_device_descriptor desc = {0};
libusb_get_device_descriptor(device, &desc);
port = libusb_get_port_number(device);
printf("Vendor:Device = %04x:%04x Port: %d\n", desc.idVendor, desc.idProduct,port);
}
libusb_free_device_list(list, count);
libusb_exit(context);
}
What I need now is to know (from the C application) what v4l2 device number is related to the usb camera port, eg. I've got two webcam (same vendor ID) connected which appear as /dev/video0 and /dev/video1 respectively and I can get the connected port for each one using the above code, but, how can I know which ports are connected each one?
I tried to get information from the devices using ioctl calls as it is recommended in this question but when I run the code:
int checkvideodev()
{
int fd;
struct video_capability video_cap;
struct video_window video_win;
struct video_picture video_pic;
if((fd = open("/dev/video0", O_RDONLY)) == -1){
perror("cam_info: Can't open device");
return 1;
}
if(xioctl(fd, VIDIOCGCAP, &video_cap) == -1)
perror("cam_info: Can't get capabilities");
else {
printf("Name:\t\t '%s'\n", video_cap.name);
printf("Minimum size:\t%d x %d\n", video_cap.minwidth, video_cap.minheight);
printf("Maximum size:\t%d x %d\n", video_cap.maxwidth, video_cap.maxheight);
}
if(xioctl(fd, VIDIOCGWIN, &video_win) == -1)
perror("cam_info: Can't get window information");
else
printf("Current size:\t%d x %d\n", video_win.width, video_win.height);
if(xioctl(fd, VIDIOCGPICT, &video_pic) == -1)
perror("cam_info: Can't get picture information");
else
printf("Current depth:\t%d\n", video_pic.depth);
close(fd);
return 0;
}
I've got the next errors:
cam_info: Can't get capabilities: Inappropriate ioctl for device
cam_info: Can't get window information: Inappropriate ioctl for device
cam_info: Can't get picture information: Inappropriate ioctl for device
If I'm checking through command line for instance I can get the capabilities without issues running:
v4l2-ctl --device-/dev/video0 --list-formats-ext
Any ideas how can this be done?
Thanks in advance.
I don't know if this specifically answers your question, but you can get useful information by globbing certain patterns under /dev or /sys, for example this will return the full device path (including PCI bus) of each video device,
#include <glob.h>
#include <unistd.h>
void list_videos() {
int i;
glob_t globbuf;
if (glob("/sys/class/video4linux/video*", 0, NULL, &globbuf) != 0) {
perror("glob");
return;
}
for (i=0; i < globbuf.gl_pathc; i++) {
char buf[256] = {};
if (readlink(globbuf.gl_pathv[i], buf, sizeof(buf)-1) > 0) {
puts(buf);
}
}
}
On one system with 2 cameras this prints,
../../devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1.1/2-1.1:1.0/video4linux/video0
../../devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3:1.0/video4linux/video1
Other interesting glob strings include /dev/v4l/by-id/* and /dev/v4l/by-path/*.
I've got a compound USB + CDC device I built using a PIC32 microcontroller, and I'm trying to connect to the device and send some data to the CDC data interface endpoint from my Mac.
I know the circuit works 100%, as the device registers as both a HID joystick, and I'm able to connect to the device using Zoc terminal, on /dev/tty.usbmodemfa132. I can send commands with Zoc, and see my MCU responding to these commands by blinking some LEDs on the circuit.
I'm running this on Mac OS X Mavericks, but had the same problem with a similar example I gave up on, a few weeks ago on Mountain Lion.
My code looks like follows:
// Includes -----------------------------------------------------------------------------------------------------------
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#include <unistd.h>
// Defines ------------------------------------------------------------------------------------------------------------
#define VID 0x04d8
#define PID 0x005e
#define CDC_DATA_INTERFACE_ID 2
// Function Declarations ----------------------------------------------------------------------------------------------
void print_device(libusb_device *device);
void send(libusb_context *usb_context, uint16_t vid, uint16_t pid);
// Function Definitions -----------------------------------------------------------------------------------------------
/**
* main
*/
int main(int argc, char **argv)
{
libusb_device **usb_devices = NULL;
libusb_context *usb_context = NULL;
ssize_t device_count = 0;
bool debug_enabled = false;
int c;
// Collect command line attributes
while ( (c = getopt(argc, argv, "d")) != -1) {
switch (c) {
case 'd':
debug_enabled = true;
break;
}
}
// Initialize USB context
int result = libusb_init(&usb_context);
if(result < 0) {
printf("Unable to initialise libusb!");
return EXIT_FAILURE;
}
// Turn debug mode on/off
if(debug_enabled) {
libusb_set_debug(usb_context, 3);
}
// Get USB device list
device_count = libusb_get_device_list(usb_context, &usb_devices);
if(device_count < 0) {
puts("Unable to retrieve USB device list!");
}
// Iterate and print devices
puts("VID PID Manufacturer Name\n------ ------ -------------------");
for (int i = 0; i < device_count; i++) {
print_device(usb_devices[i]);
}
// Attempt to send data
send(usb_context, VID, PID);
// Cleanup and exit
libusb_free_device_list(usb_devices, 1);
libusb_exit(usb_context);
return EXIT_SUCCESS;
}
/**
* print_device
*/
void print_device(libusb_device *device)
{
struct libusb_device_descriptor device_descriptor;
struct libusb_device_handle *device_handle = NULL;
// Get USB device descriptor
int result = libusb_get_device_descriptor(device, &device_descriptor);
if (result < 0) {
printf("Failed to get device descriptor!");
}
// Only print our devices
if(VID == device_descriptor.idVendor && PID == device_descriptor.idProduct) {
// Print VID & PID
printf("0x%04x 0x%04x", device_descriptor.idVendor, device_descriptor.idProduct);
} else {
return;
}
// Attempt to open the device
int open_result = libusb_open(device, &device_handle);
if (open_result < 0) {
libusb_close(device_handle);
return;
}
// Print the device manufacturer string
char manufacturer[256] = " ";
if (device_descriptor.iManufacturer) {
libusb_get_string_descriptor_ascii(device_handle, device_descriptor.iManufacturer,
(unsigned char *)manufacturer, sizeof(manufacturer));
printf(" %s", manufacturer);
}
puts("");
libusb_close(device_handle);
}
/**
* send
*/
void send(libusb_context *usb_context, uint16_t vid, uint16_t pid)
{
libusb_device_handle *device_handle;
device_handle = libusb_open_device_with_vid_pid(usb_context, vid, pid);
if (device_handle == NULL) {
puts("Unable to open device by VID & PID!");
return;
}
puts("Device successfully opened");
unsigned char *data = (unsigned char *)"test";
if (libusb_kernel_driver_active(device_handle, CDC_DATA_INTERFACE_ID)) {
puts("Kernel driver active");
if (libusb_detach_kernel_driver(device_handle, CDC_DATA_INTERFACE_ID)) {
puts("Kernel driver detached");
}
} else {
puts("Kernel driver doesn't appear to be active");
}
int result = libusb_claim_interface(device_handle, CDC_DATA_INTERFACE_ID);
if (result < 0) {
puts("Unable to claim interface!");
libusb_close(device_handle);
return;
}
puts("Interface claimed");
int written = 0;
result = libusb_bulk_transfer(device_handle, (3 | LIBUSB_ENDPOINT_OUT), data, 4, &written, 0);
if (result == 0 && written == 4) {
puts("Send success");
} else {
puts("Send failed!");
}
result = libusb_release_interface(device_handle, CDC_DATA_INTERFACE_ID);
if (result != 0) {
puts("Unable to release interface!");
}
libusb_close(device_handle);
}
I'm getting the following error output:
libusb: 0.828223 error [darwin_open] USBDeviceOpen: another process has device opened for exclusive access
libusb: 0.828241 info [darwin_open] device open for access
Device successfully opened
Kernel driver doesn't appear to be active
libusb: 0.828641 error [darwin_claim_interface] USBInterfaceOpen: another process has device opened for exclusive access
Unable to claim interface!
libusb: 0.828766 info [event_thread_main] thread exiting
Is there a way I can release the USB device from the other process, freeing it up so I can claim it?
Is there an alternative way I can connect to /dev/tty.usbmodemfa132 to send and receive data to the CDC interface on the USB device?
An alternative to libusb perhaps?
That's right. While libusb seems to be all-powerful in Linux, you cannot use it to connect to a USB CDC interface on Mac OS X because that interface is already claimed by the AppleUSBCDCACM driver.
What you should do is use the standard way that people connect to serial ports. This will be easier because you don't have to worry about endpoints and bulk transfers and such. Here is some example cross-platform C code I wrote for one of our CDC-based products that connects to a COM port to read and write some data (source). It uses the standard functions open, read, and write.
// Uses POSIX functions to send and receive data from a Maestro.
// NOTE: You must change the 'const char * device' line below.
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#ifdef _WIN32
#define O_NOCTTY 0
#else
#include <termios.h>
#endif
// Gets the position of a Maestro channel.
// See the "Serial Servo Commands" section of the user's guide.
int maestroGetPosition(int fd, unsigned char channel)
{
unsigned char command[] = {0x90, channel};
if(write(fd, command, sizeof(command)) == -1)
{
perror("error writing");
return -1;
}
unsigned char response[2];
if(read(fd,response,2) != 2)
{
perror("error reading");
return -1;
}
return response[0] + 256*response[1];
}
// Sets the target of a Maestro channel.
// See the "Serial Servo Commands" section of the user's guide.
// The units of 'target' are quarter-microseconds.
int maestroSetTarget(int fd, unsigned char channel, unsigned short target)
{
unsigned char command[] = {0x84, channel, target & 0x7F, target >> 7 & 0x7F};
if (write(fd, command, sizeof(command)) == -1)
{
perror("error writing");
return -1;
}
return 0;
}
int main()
{
// Open the Maestro's virtual COM port.
const char * device = "\\\\.\\USBSER000"; // Windows, "\\\\.\\COM6" also works
//const char * device = "/dev/ttyACM0"; // Linux
//const char * device = "/dev/cu.usbmodem00034567"; // Mac OS X
int fd = open(device, O_RDWR | O_NOCTTY);
if (fd == -1)
{
perror(device);
return 1;
}
#ifndef _WIN32
struct termios options;
tcgetattr(fd, &options);
options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
options.c_oflag &= ~(ONLCR | OCRNL);
tcsetattr(fd, TCSANOW, &options);
#endif
int position = maestroGetPosition(fd, 0);
printf("Current position is %d.\n", position);
int target = (position < 6000) ? 7000 : 5000;
printf("Setting target to %d (%d us).\n", target, target/4);
maestroSetTarget(fd, 0, target);
close(fd);
return 0;
}
If you want to use some USB device that is also recognised by the Apple FTDI serial driver, you can first unload the driver:
sudo kextunload -b com.apple.driver.AppleUSBFTDI
After that you can use it through libusb normally.
For other devices that are recognised as serial devices, you probably need to unload some other driver.
The problem seems to be due to a conflict between different drivers, which use the same libraries, and in my case they were related to previous Samsung device installations. i had solved this way:
kextstat | grep -v apple
To have a return like this:
70 0 0x57574000 0x3000 0x2000 com.devguru.driver.SamsungComposite (1.2.4) <33 4 3>
72 0 0x57831000 0x7000 0x6000 com.devguru.driver.SamsungACMData (1.2.4) <71 33 5 4 3>
94 0 0x57674000 0x3000 0x2000 com.devguru.driver.SamsungACMControl (1.2.4) <33 4 3>
Then:
$ sudo kextunload -b com.devguru.driver.SamsungComposite
$ sudo kextunload -b com.devguru.driver.SamsungACMData
$ sudo kextunload -b com.devguru.driver.SamsungACMControl
Done. Enjoy