55#include < memory>
66#include < termios.h>
77#include < cstring>
8- #include < sys/ioctl.h>
98#include < chrono>
9+ #include < thread>
1010
1111static std::unique_ptr<CelestronDewPower> celestronDewPower (new CelestronDewPower());
1212
@@ -149,8 +149,6 @@ bool CelestronDewPower::Handshake()
149149
150150 LOG_INFO (" Setting serial speed to 9600 baud." );
151151
152- m_IsRTSCTS = detectRTSCTS (); // Detect RTS/CTS if applicable
153-
154152 // Get version
155153 if (!getDewPowerControllerVersion ())
156154 {
@@ -181,8 +179,15 @@ bool CelestronDewPower::Handshake()
181179 {
182180 if (response.command () == PORTCTRL_GET_PORT_INFO )
183181 {
182+ // The controller only reports full telemetry (enabled/
183+ // shorted/power/voltage, >= 7 bytes) when a port is
184+ // actively drawing current; an idle port -- the normal
185+ // state at connection time -- replies with just the
186+ // 1-byte port type. Only require that one byte here so
187+ // capability detection doesn't silently misclassify
188+ // every idle port as DC output (portType 0).
184189 AUXBuffer data = response.getDataBuffer ();
185- if (data.size () >= 7 )
190+ if (! data.empty () )
186191 {
187192 uint8_t portType = data[0 ];
188193 m_PortTypes[i] = portType;
@@ -358,6 +363,13 @@ bool CelestronDewPower::processResponse(AUXCommand &m)
358363 case PORTCTRL_SET_LED_BRIGHTNESS :
359364 // These are "set" commands, no specific data to process in response beyond success/failure
360365 break ;
366+ case PORTCTRL_NAK :
367+ {
368+ AUXBuffer data = m.getDataBuffer ();
369+ LOGF_DEBUG (" Controller NAK'd command 0x%02X (not applicable to that port)." ,
370+ data.empty () ? 0 : data[0 ]);
371+ break ;
372+ }
361373 default :
362374 break ;
363375 }
@@ -440,7 +452,7 @@ int CelestronDewPower::sendBuffer(AUXBuffer buf)
440452 {
441453 int n;
442454
443- if (aux_tty_write ((char * )buf.data (), buf.size (), CTS_TIMEOUT , &n) != TTY_OK )
455+ if (aux_tty_write ((char * )buf.data (), buf.size (), &n) != TTY_OK )
444456 return 0 ;
445457
446458 std::this_thread::sleep_for (std::chrono::milliseconds (50 ));
@@ -478,60 +490,18 @@ bool CelestronDewPower::sendAUXCommand(AUXCommand &command)
478490// //////////////////////////////////////////////////////////////////////////////
479491// Wrap functions around the standard driver communication functions tty_read
480492// and tty_write.
481- // When the communication is serial, these wrap functions implement the
482- // Celestron hardware handshake used by telescope serial ports AUX and PC.
483- // When the communication is by network, these wrap functions are trasparent.
484- // Read and write calls are passed, as is, to the standard functions tty_read
485- // and tty_write.
486- // 16-Feb-2020 Fabrizio Pollastri <mxgbot@gmail.com>
493+ //
494+ // This controller only ever communicates over a USB CDC-ACM virtual serial
495+ // port (/dev/ttyACM*), never a real RS-232 half-duplex AUX/PC port, so
496+ // unlike INDI's CelestronAUX telescope driver (which this AUX protocol was
497+ // adapted from) there is no hardware RTS/CTS flow control or byte-echo to
498+ // handle here: USB CDC-ACM modem-control lines are virtual and commonly
499+ // read back as permanently asserted regardless of real hardware state,
500+ // which previously caused a false-positive half-duplex detection here and
501+ // broke every connection. Plain full-duplex tty_read/tty_write is correct,
502+ // matching drivers/focuser/celestronauxpacket.cpp which talks to other
503+ // Celestron AUX-bus accessories the same way.
487504// //////////////////////////////////////////////////////////////////////////////
488- void CelestronDewPower::setRTS (bool rts)
489- {
490- if (ioctl (PortFD, TIOCMGET , &m_ModemControl) == -1 )
491- LOGF_ERROR (" Error getting handshake lines %s(%d)." , strerror (errno), errno);
492- if (rts)
493- m_ModemControl |= TIOCM_RTS ;
494- else
495- m_ModemControl &= ~TIOCM_RTS ;
496- if (ioctl (PortFD, TIOCMSET , &m_ModemControl) == -1 )
497- LOGF_ERROR (" Error setting handshake lines %s(%d)." , strerror (errno), errno);
498- }
499-
500- // ///////////////////////////////////////////////////////////////////////////////////
501- // /
502- // ///////////////////////////////////////////////////////////////////////////////////
503- bool CelestronDewPower::waitCTS (float timeout)
504- {
505- float step = timeout / 20 .;
506- for (; timeout >= 0 ; timeout -= step)
507- {
508- std::this_thread::sleep_for (std::chrono::milliseconds (static_cast <int >(step)));
509- if (ioctl (PortFD, TIOCMGET , &m_ModemControl) == -1 )
510- {
511- LOGF_ERROR (" Error getting handshake lines %s(%d)." , strerror (errno), errno);
512- return 0 ;
513- }
514- if (m_ModemControl & TIOCM_CTS )
515- return 1 ;
516- }
517- return 0 ;
518- }
519-
520- // ///////////////////////////////////////////////////////////////////////////////////
521- // /
522- // ///////////////////////////////////////////////////////////////////////////////////
523- bool CelestronDewPower::detectRTSCTS ()
524- {
525- setRTS (1 );
526- bool retval = waitCTS (300 .);
527- setRTS (0 );
528- return retval;
529- }
530-
531-
532- // ///////////////////////////////////////////////////////////////////////////////////
533- // /
534- // ///////////////////////////////////////////////////////////////////////////////////
535505bool CelestronDewPower::tty_set_speed (speed_t speed)
536506{
537507 struct termios tty_setting;
@@ -578,11 +548,6 @@ int CelestronDewPower::aux_tty_read(char *buf, int bufsiz, int timeout, int *n)
578548 int errcode;
579549 DEBUGF (DBG_SERIAL , " aux_tty_read: %d" , PortFD);
580550
581- // if hardware flow control is required, set RTS to off to receive: PC port
582- // bahaves as half duplex.
583- if (m_IsRTSCTS)
584- setRTS (0 );
585-
586551 if ((errcode = tty_read (PortFD, buf, bufsiz, timeout, n)) != TTY_OK )
587552 {
588553 char errmsg[MAXRBUF ] = {0 };
@@ -596,27 +561,11 @@ int CelestronDewPower::aux_tty_read(char *buf, int bufsiz, int timeout, int *n)
596561// ///////////////////////////////////////////////////////////////////////////////////
597562// /
598563// ///////////////////////////////////////////////////////////////////////////////////
599- int CelestronDewPower::aux_tty_write (char *buf, int bufsiz, float timeout, int *n)
564+ int CelestronDewPower::aux_tty_write (char *buf, int bufsiz, int *n)
600565{
601- int errcode, ne ;
566+ int errcode;
602567 char errmsg[MAXRBUF ];
603568
604- // DEBUGF(DBG_CAUX, "aux_tty_write: %d", PortFD);
605-
606- // if hardware flow control is required, set RTS to on then wait for CTS
607- // on to write: PC port bahaves as half duplex. RTS may be already on.
608- if (m_IsRTSCTS)
609- {
610- DEBUG (DBG_SERIAL , " aux_tty_write: set RTS" );
611- setRTS (1 );
612- DEBUG (DBG_SERIAL , " aux_tty_write: wait CTS" );
613- if (!waitCTS (timeout))
614- {
615- LOGF_ERROR (" Error getting handshake lines %s(%d).\n " , strerror (errno), errno);
616- return TTY_TIME_OUT ;
617- }
618- }
619-
620569 errcode = tty_write (PortFD, buf, bufsiz, n);
621570
622571 if (errcode != TTY_OK )
@@ -626,32 +575,6 @@ int CelestronDewPower::aux_tty_write(char *buf, int bufsiz, float timeout, int *
626575 return errcode;
627576 }
628577
629- // if hardware flow control is required, Wait for tx complete, set RTS to
630- // off, to receive (half duplex).
631- if (m_IsRTSCTS)
632- {
633- DEBUG (DBG_SERIAL , " aux_tty_write: clear RTS" );
634- std::this_thread::sleep_for (std::chrono::milliseconds (50 ));
635- setRTS (0 );
636-
637- // ports requiring hardware flow control echo all sent characters,
638- // verify them.
639- DEBUG (DBG_SERIAL , " aux_tty_write: verify echo" );
640- if ((errcode = tty_read (PortFD, errmsg, *n, READ_TIMEOUT , &ne)) != TTY_OK )
641- {
642- tty_error_msg (errcode, errmsg, MAXRBUF );
643- LOGF_ERROR (" %s" , errmsg);
644- return errcode;
645- }
646-
647- if (*n != ne)
648- return TTY_WRITE_ERROR ;
649-
650- for (int i = 0 ; i < ne; i++)
651- if (buf[i] != errmsg[i])
652- return TTY_WRITE_ERROR ;
653- }
654-
655578 return TTY_OK ;
656579}
657580
@@ -739,6 +662,8 @@ bool CelestronDewPower::getPortInfo(uint8_t portNumber)
739662 if (response.command () == PORTCTRL_GET_PORT_INFO )
740663 {
741664 // RESP: <0 type><1 enabled><2 isShorted><3:4 power(mW)><5:6 VoltageLevel (mV)>
665+ // Only present in full when the port is actively drawing
666+ // current; an idle port replies with just the 1-byte type.
742667 AUXBuffer data = response.getDataBuffer ();
743668 if (data.size () >= 7 )
744669 {
@@ -749,6 +674,11 @@ bool CelestronDewPower::getPortInfo(uint8_t portNumber)
749674 portNumber, data[0 ], data[1 ], data[2 ], (data[3 ] << 8 ) | data[4 ], (data[5 ] << 8 ) | data[6 ]);
750675 return true ;
751676 }
677+ else if (!data.empty ())
678+ {
679+ LOGF_DEBUG (" Port %d Info: Type=%d (idle, no telemetry)" , portNumber, data[0 ]);
680+ return true ;
681+ }
752682 }
753683 }
754684 return false ;
0 commit comments