Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
0782756
Add libserialport to make/Cmake
MCUdude Aug 31, 2023
b744b19
Initial support for serial port discovery using libserialport
MCUdude Aug 31, 2023
4107aa3
Use compile time constants to set string lengths
MCUdude Aug 31, 2023
6e390d0
Remove comparisons that allways returns true
MCUdude Sep 1, 2023
6976e75
Apply @stefanrueger's patch
MCUdude Sep 1, 2023
37d896f
Remove unnecessary branch
MCUdude Sep 1, 2023
385f210
Remove exits
MCUdude Sep 1, 2023
d9912f1
Reduce error messages to warnings
MCUdude Sep 1, 2023
5aea6bd
Only deploy the serial port discovery when pgm->conntype == CONNTYPE_…
MCUdude Sep 2, 2023
ca245da
Make sure serialport is unique
MCUdude Sep 2, 2023
9e65675
Use dynamic memory allocation for sernum and port
MCUdude Sep 3, 2023
8258e08
Support partial serial numbers
MCUdude Sep 3, 2023
efce224
Rename serialadapter functions
MCUdude Sep 3, 2023
5be3edb
Add support for "usb" suffix when specifying USB VID and PID
MCUdude Sep 3, 2023
af6fc08
Add print_available_serialports function
MCUdude Sep 3, 2023
d519286
Add missing usb prefix
MCUdude Sep 3, 2023
58b4826
Search for matching serial adapter vid/pid in avrdude.conf
MCUdude Sep 3, 2023
e46a00a
Formatting
MCUdude Sep 3, 2023
f40366c
Require "usb:" prefix
MCUdude Sep 3, 2023
e0abcaf
Allocate space for tokens dynamically
MCUdude Sep 3, 2023
1389463
Add support for trailing serial number matching using ...[end_of_sn]
MCUdude Sep 3, 2023
e1fb8c3
Fix token memory allocation issue
MCUdude Sep 4, 2023
d234bd1
Utilize usbsn if specified in avrduderc
MCUdude Sep 4, 2023
6576825
Do not print all available serial ports unless ...
MCUdude Sep 4, 2023
53a6775
Make it possible to override serial numbers specified in avrduderc
MCUdude Sep 4, 2023
c51ec19
Harden port printing logic
MCUdude Sep 4, 2023
2268d8e
Fix another port print bug
MCUdude Sep 4, 2023
970953d
Only suggest -P usb:[vid]:[pid](:[sn]) if the serial adapter is unique
MCUdude Sep 4, 2023
bd1b86f
Allow serial adapters to override the default baudrate
MCUdude Sep 4, 2023
c6e832a
Fix segfault
MCUdude Sep 5, 2023
6e3722b
Add more serial adapters
MCUdude Sep 5, 2023
f06f18e
Add @stefanrueger's 0001-Fix-sublte-parsing-problems patch
MCUdude Sep 5, 2023
23fad1a
Apply @stefanrueger's 0001-Draft-auxiliary-port-discovery-functions p…
MCUdude Sep 5, 2023
2baf87d
Print serial numbers when two or more serial adapters has the same VI…
MCUdude Sep 6, 2023
af3d4e5
Remove unused functions and improve serial number matching
MCUdude Sep 6, 2023
d2cacf0
Only suggest serial adapters provided in avrduderc if...
MCUdude Sep 7, 2023
d89cf73
Print all serial adapter alternatives if specified serial adapter
MCUdude Sep 7, 2023
88bbea8
Fix issue where serial adapters with non-matching serial number were …
MCUdude Sep 8, 2023
0eb91e4
Add get_libserialport_data function
MCUdude Sep 9, 2023
3df2b19
Add missing rv
MCUdude Sep 10, 2023
77cbffc
Finally fix libserialport autoconf/make build issues
MCUdude Sep 10, 2023
602b575
Replace the last few remaining tabs with spaces
MCUdude Sep 10, 2023
862cc57
Mention serial port discovery in the docs
MCUdude Sep 10, 2023
e553c29
Apply @stefanrueger's parsing improvement patch
MCUdude Sep 13, 2023
c251450
Improve serial number matching logic
MCUdude Sep 13, 2023
d0f63ee
Add sa_num_matches_by_sea function
MCUdude Sep 13, 2023
2d28a7b
Divide more functionality into functions
MCUdude Sep 13, 2023
42c0655
Simplify/optimize setport_from_serialadapter() and setport_from_vid_p…
MCUdude Sep 14, 2023
471e66f
move sa_flag_unique() inside get_libserialport_data()
MCUdude Sep 14, 2023
efd1716
Rename for loop counter variables
MCUdude Sep 14, 2023
d7dc844
Formatting
MCUdude Sep 14, 2023
98f0640
Improve print_available_serialports() function
MCUdude Sep 16, 2023
7511a5d
Apply @stenfanruegers 0001-Refactor-serialadapter patch
MCUdude Sep 18, 2023
8730fc1
Apply @stefanrueger's 0001-Sort-list-of-plugged-in-SERPORTs-according…
MCUdude Sep 19, 2023
6694e98
Don't suggest usb:vid:pid for serial ports where vid is zero
MCUdude Sep 19, 2023
ba72908
Move str_endnumber() to strutil.c
MCUdude Sep 19, 2023
28e6187
Implement and document -P ?s and -P ?sa
stefanrueger Sep 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ if(USE_STATIC_LIBS)
set(PREFERRED_LIBFTDI libftdi.a ftdi)
set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1)
set(PREFERRED_LIBREADLINE libreadline.a)
set(PREFERRED_LIBSERIALPORT libserialport.a)
set(PREFERRED_LIBGPIOD libgpiod.a gpiod)
else()
set(PREFERRED_LIBELF elf)
Expand All @@ -134,6 +135,7 @@ else()
set(PREFERRED_LIBFTDI ftdi)
set(PREFERRED_LIBFTDI1 ftdi1)
set(PREFERRED_LIBREADLINE readline)
set(PREFERRED_LIBSERIALPORT serialport)
set(PREFERRED_LIBGPIOD gpiod)
endif()

Expand Down Expand Up @@ -225,6 +227,15 @@ elseif(MSVC)
set(HAVE_LIBREADLINE 1)
endif()

#-------------------------------------
# Find libserialport

find_library(HAVE_LIBSERIALPORT NAMES ${PREFERRED_LIBSERIALPORT})
if(HAVE_LIBSERIALPORT)
set(LIB_LIBSERIALPORT ${HAVE_LIBSERIALPORT})
set(HAVE_LIBSERIALPORT 1)
endif()

# -------------------------------------
# Find libgpiod, if needed
if(HAVE_LINUXGPIO)
Expand Down Expand Up @@ -319,6 +330,7 @@ if (DEBUG_CMAKE)
message(STATUS "HAVE_LIBFTDI: ${HAVE_LIBFTDI}")
message(STATUS "HAVE_LIBFTDI1: ${HAVE_LIBFTDI1}")
message(STATUS "HAVE_LIBREADLINE: ${HAVE_LIBREADLINE}")
message(STATUS "HAVE_LIBSERIALPORT: ${HAVE_LIBSERIALPORT}")
message(STATUS "HAVE_LIBELF_H: ${HAVE_LIBELF_H}")
message(STATUS "HAVE_LIBELF_LIBELF_H: ${HAVE_LIBELF_LIBELF_H}")
message(STATUS "HAVE_USB_H: ${HAVE_USB_H}")
Expand Down Expand Up @@ -377,6 +389,12 @@ else()
message(STATUS "DON'T HAVE libreadline")
endif()

if(HAVE_LIBSERIALPORT)
message(STATUS "DO HAVE libserialport")
else()
message(STATUS "DON'T HAVE libserialport")
endif()

if(BUILD_DOC)
message(STATUS "ENABLED doc")
else()
Expand Down
3 changes: 3 additions & 0 deletions src/cmake_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,6 @@

/* Define to 1 if you have the `readline' library (-lreadline). */
#cmakedefine HAVE_LIBREADLINE 1

/* Define to 1 if you have the `serialport' library */
#cmakedefine HAVE_LIBSERIALPORT 1
18 changes: 18 additions & 0 deletions src/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ if test x$have_libhidapi = xyes; then
fi
AC_SUBST(LIBHIDAPI, $LIBHIDAPI)

AH_TEMPLATE([HAVE_LIBSERIALPORT],
[Define if libserialport is found])
AC_CHECK_LIB([serialport], [sp_open], [have_libserialport=yes])
if test x$have_libserialport = xyes; then
case $target in
*)
LIBSERIALPORT="-lserialport"
;;
esac
AC_DEFINE([HAVE_LIBSERIALPORT])
AC_CHECK_HEADERS([libserialport.h])
fi

AH_TEMPLATE([HAVE_LIBFTDI1],
[Define if FTDI support is enabled via libftdi1])
Expand Down Expand Up @@ -604,6 +616,12 @@ else
echo "DON'T HAVE libreadline"
fi

if test x$have_libserialport = xyes; then
echo "DO HAVE libserialport"
else
echo "DON'T HAVE libserialport"
fi

if test x$have_pthread = xyes; then
echo "DO HAVE pthread"
else
Expand Down
3 changes: 3 additions & 0 deletions src/libavrdude.h
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,9 @@ typedef struct {
extern "C" {
#endif

int find_serialport_adapter(const SERIALADAPTER *ser, char *port, char *sernum);
int find_serialport_vid_pid(char *port, int vid, int pid, char *sernum);

int str_starts(const char *str, const char *starts);
int str_eq(const char *str1, const char *str2);
int str_contains(const char *str, const char *substr);
Expand Down
49 changes: 49 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,55 @@ int main(int argc, char * argv [])
}
}

// Divide the port string into tokens separated by colon(s).
// There are four ways a port string can be presented:
// 1) -P [serialadapter]
// 2) -P [serialadapter]:[sernum]
// 3) -P [usbvid]:[usbpid]
// 4) -P [usbvid]:[usbpid]:[sernum]
char port_str[256];
char port_tok[3][256];
memset(port_tok, 0, sizeof(port_tok));
strcpy(port_str, (const char *)port);
char *tok = strtok(port_str, ":");
for (int i = 0; i < 3; i++) {
if (!tok)
break;
strcpy(port_tok[i], tok);
tok = strtok(NULL, ":");
}

// Use libserialport to find the actual serial port
const char *seradapter;
SERIALADAPTER *ser = locate_programmer_set(programmers, port_tok[0], &seradapter);
if (is_serialadapter(ser)) {
if (find_serialport_adapter(ser, port, port_tok[1]) < 0) {
if (port_tok[1][0])
pmsg_error("serial adapter %s with serial number %s not found\n", seradapter, port_tok[1]);
else
pmsg_error("serial adapter %s not found\n", seradapter);
exit(1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we exit here? Say, there is a serialadapter ch340 in avrdude.conf. -P ch340 checks if there is a serial adapter ch340 connected and does not find one. OK, rather then exiting, it could still allow the open() routine to open the file ch340; after all it could be a symbolic link to an existing port for all we know

}
} else if (is_programmer(ser)) {
if (port_tok[1][0])
pmsg_error("invalid serial adapter %s with serial number %s specified\n", seradapter, port_tok[1]);
else
pmsg_error("invalid serial adapter %s specified\n", port_tok[0]);
exit(1);
} else {
// Port or usb vid/pid
int vid, pid;
if (sscanf(port_tok[0], "%x", &vid) > 0 && sscanf(port_tok[1], "%x", &pid) > 0) {
if(find_serialport_vid_pid(port, vid, pid, port_tok[2]) < 0) {
if (port_tok[2][0])
pmsg_error("serial adapter with USB VID %s and PID %s and serial number %s not found\n", port_tok[0], port_tok[1], port_tok[2]);
else
pmsg_error("serial adapter with USB VID %s and PID %s not found\n", port_tok[0], port_tok[1]);
exit(1);
}
}
}

/*
* open the programmer
*/
Expand Down
132 changes: 132 additions & 0 deletions src/serialadapter.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* AVRDUDE - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2023 Stefan Rueger <[email protected]>
* Copyright (C) 2023 Hans Eirik Bull
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -24,6 +25,137 @@
#include "avrdude.h"
#include "libavrdude.h"

#ifdef HAVE_LIBSERIALPORT

#include <libserialport.h>

int find_serialport_adapter(const SERIALADAPTER *ser, char *serport, char *sernum) {
int rv = -1;
/* A pointer to a null-terminated array of pointers to
* struct sp_port, which will contain the ports found */
struct sp_port **port_list;

/* Call sp_list_ports() to get the ports. The port_list
* pointer will be updated to refer to the array created */
enum sp_return result = sp_list_ports(&port_list);

if (result != SP_OK) {
pmsg_error("sp_list_ports() failed!\n");
return -1;
}

for (int i = 0; port_list[i]; i++) {
struct sp_port *prt = port_list[i];
int usb_vid, usb_pid;
sp_get_port_usb_vid_pid(prt, &usb_vid, &usb_pid);

// USB VID match
if(usb_vid == ser->usbvid) {
for (LNODEID usbpid = lfirst(ser->usbpid); usbpid; usbpid = lnext(usbpid)) {
// USB PID match
if (usb_pid == *(int *)(ldata(usbpid))) {
// SN present
if (sernum && sernum[0]) {
// SN matches
char *s = sp_get_port_usb_serial(prt);
if(s) {
if (str_eq(sernum, s)) {
strcpy(serport, sp_get_port_name(prt));
rv = 0;
}
}
// SN does not match
else {
continue;
}
}
// SN not present
else {
char *p = sp_get_port_name(prt);
if(p) {
strcpy(serport, p);
rv = 0;
}
else
rv = -1;
}
}
}
}
}

sp_free_port_list(port_list); // Free the array created by sp_list_ports()
return rv;
}

int find_serialport_vid_pid(char *serport, int vid, int pid, char *sernum) {
int rv = -1;
/* A pointer to a null-terminated array of pointers to
* struct sp_port, which will contain the ports found */
struct sp_port **port_list;

/* Call sp_list_ports() to get the ports. The port_list
* pointer will be updated to refer to the array created */
enum sp_return result = sp_list_ports(&port_list);

if (result != SP_OK) {
pmsg_error("sp_list_ports() failed!\n");
return -1;
}

for (int i = 0; port_list[i]; i++) {
struct sp_port *prt = port_list[i];
int usb_vid, usb_pid;
sp_get_port_usb_vid_pid(prt, &usb_vid, &usb_pid);

// USB VID and PIDmatch
if(usb_vid == vid && usb_pid == pid) {
// SN present
if (sernum && sernum[0]) {
// SN matches
char *s = sp_get_port_usb_serial(prt);
if(s) {
if (str_eq(sernum, s)) {
strcpy(serport, sp_get_port_name(prt));
rv = 0;
}
}
// SN does not match
else {
continue;
}
}
// SN not present
else {
char *p = sp_get_port_name(prt);
if(p) {
strcpy(serport, p);
rv = 0;
}
else
rv = -1;
}
}
}

sp_free_port_list(port_list); // Free the array created by sp_list_ports()
return rv;
}

#else

int find_serialport_adapter(const SERIALADAPTER *ser, char *port, char *sernum) {
pmsg_error("Avrdude built without libserialport support; please compile again with libserialport installed\n");
return -1;
}

int find_serialport_vid_pid(char *port, int vid, int pid, char *sernum) {
pmsg_error("Avrdude built without libserialport support; please compile again with libserialport installed\n");
return -1;
}

#endif

void list_serialadapters(FILE *fp, const char *prefix, LISTID programmers) {
LNODEID ln1, ln2, ln3;
SERIALADAPTER *sea;
Expand Down