2121#include <string.h>
2222#include <stdio.h>
2323#include <stdlib.h>
24+ #include <unistd.h>
2425
2526#include "avrdude.h"
2627#include "libavrdude.h"
@@ -130,6 +131,13 @@ static SERPORT *get_libserialport_data(int *np) {
130131 return sp ;
131132}
132133
134+ // Free memory allocated from get_libserialport_data()
135+ static void free_libserialport_data (SERPORT * sp , int n ) {
136+ for (int k = 0 ; sp && k < n ; k ++ )
137+ free (sp [k ].sernum ), free (sp [k ].port );
138+ free (sp );
139+ }
140+
133141// Returns a NULL-terminated malloc'd list of items in SERPORT list spa that are not in spb
134142SERPORT * * sa_spa_not_spb (SERPORT * spa , int na , SERPORT * spb , int nb ) {
135143 SERPORT * * ret = cfg_malloc (__func__ , (na + 1 )* sizeof * ret );
@@ -266,10 +274,7 @@ int setport_from_serialadapter(char **portp, const SERIALADAPTER *sea, const cha
266274 if (m == 0 || sa_num_matches_by_sea (sea , sernum , sp + i , 1 ) == 1 )
267275 sa_print_specs (sp , n , i );
268276 }
269-
270- for (int k = 0 ; k < n ; k ++ )
271- free (sp [k ].sernum ), free (sp [k ].port );
272- free (sp );
277+ free_libserialport_data (sp , n );
273278
274279 return rv ;
275280}
@@ -294,14 +299,62 @@ int setport_from_vid_pid(char **portp, int vid, int pid, const char *sernum) {
294299 if (m == 0 || sa_num_matches_by_ids (vid , pid , sernum , sp + i , 1 ) == 1 )
295300 sa_print_specs (sp , n , i );
296301 }
297-
298- for (int k = 0 ; k < n ; k ++ )
299- free (sp [k ].sernum ), free (sp [k ].port );
300- free (sp );
302+ free_libserialport_data (sp , n );
301303
302304 return rv ;
303305}
304306
307+ // Potentially change port *portp after opening & closing it with baudrate
308+ int touch_serialport (char * * portp , int baudrate , int nwaits ) {
309+ int i , n1 , n2 ;
310+ SERPORT * sp1 , * sp2 , * * diff ;
311+ sp1 = get_libserialport_data (& n1 );
312+ if (!sp1 || n1 <= 0 || !portp )
313+ return -1 ;
314+
315+ pmsg_info ("touching serial port %s at %d baud\n" , * portp , baudrate );
316+
317+ union pinfo pinfo ;
318+ union filedescriptor fd ;
319+ pinfo .serialinfo .baud = baudrate ;
320+ pinfo .serialinfo .cflags = SERIAL_8N1 ;
321+ if (serial_open (* portp , pinfo , & fd ) == -1 ) {
322+ pmsg_error ("%s() failed to open port %s at %d baud\n" , __func__ , * portp , baudrate );
323+ return -1 ;
324+ }
325+ serial_set_dtr_rts (& fd , 1 );
326+ usleep (100 );
327+ serial_set_dtr_rts (& fd , 0 );
328+ serial_rawclose (& fd );
329+
330+ const int nloops = 32 , nap = 50 ;
331+ #if (defined(__arm__ ) || defined(__aarch64__ )) && !defined(__APPLE__ )
332+ nwaits += 2 ;
333+ #endif
334+ pmsg_info ("waiting for new port..." );
335+ usleep (400 * 1000 * nwaits );
336+ for (i = nloops ; i > 0 ; i -- ) {
337+ usleep (nap * 1000 );
338+ if ((sp2 = get_libserialport_data (& n2 ))) {
339+ diff = sa_spa_not_spb (sp2 , n2 , sp1 , n1 );
340+ if (* diff && diff [0 ]-> port && !diff [1 ]) { // Exactly one new port sprung up
341+ pmsg_notice ("new port %s discovered\n" , (* diff )-> port );
342+ if (* portp )
343+ free (* portp );
344+ * portp = cfg_strdup (__func__ , (* diff )-> port );
345+ msg_info (" %d ms:" , (nloops - i + 1 )* nap + nwaits * 400 );
346+ i = -1 ; // Leave loop
347+ }
348+ free (diff );
349+ free_libserialport_data (sp2 , n2 );
350+ }
351+ }
352+ free_libserialport_data (sp1 , n1 );
353+ msg_info (" using %s port %s\n" , i < 0 ? "new" : "same" , * portp );
354+
355+ return 0 ;
356+ }
357+
305358// List available serial ports
306359int list_available_serialports (LISTID programmers ) {
307360 // Get serial port information from libserialport
@@ -344,6 +397,11 @@ int list_available_serialports(LISTID programmers) {
344397 return -1 ;
345398}
346399
400+ int touch_serialport (char * * portp , int baudrate , int nwaits ) {
401+ pmsg_error ("avrdude built without libserialport support; please compile again with libserialport installed\n" );
402+ return -1 ;
403+ }
404+
347405#endif
348406
349407void list_serialadapters (FILE * fp , const char * prefix , LISTID programmers ) {
0 commit comments