Instrument Neutral Distributed Interface INDI  2.0.2
deepskydad_fp1.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2015 Jasem Mutlaq. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify it
5  under the terms of the GNU General Public License as published by the Free
6  Software Foundation; either version 2 of the License, or (at your option)
7  any later version.
8 
9  This program is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 
19  The full GNU General Public License is included in this distribution in the
20  file called LICENSE.
21 *******************************************************************************/
22 
23 #include "deepskydad_fp1.h"
24 
25 #include "indicom.h"
27 
28 #include <cerrno>
29 #include <cstring>
30 #include <memory>
31 #include <termios.h>
32 #include <unistd.h>
33 #include <inttypes.h>
34 #include <sys/ioctl.h>
35 
36 // We declare an auto pointer to DeepSkyDadFP1.
37 static std::unique_ptr<DeepSkyDadFP1> dsdFp1(new DeepSkyDadFP1());
38 
39 #define FLAT_CMD 40
40 #define FLAT_RES 40
41 #define FLAT_TIMEOUT 3
42 
44 {
45  setVersion(1, 1);
46 }
47 
49 {
51 
52  // Heater mode
53  IUFillSwitch(&HeaterModeS[Off], "OFF", "Off", ISS_OFF);
54  IUFillSwitch(&HeaterModeS[On], "ON", "On", ISS_OFF);
55  IUFillSwitch(&HeaterModeS[OnIfFlapOpenOrLedActive], "ON2", "On if flap open/LED active", ISS_OFF);
56  IUFillSwitchVector(&HeaterModeSP, HeaterModeS, 3, getDeviceName(), "Heater mode", "Heater mode", MAIN_CONTROL_TAB, IP_RW,
57  ISR_1OFMANY, 0, IPS_IDLE);
58 
59  // Status
60  IUFillText(&StatusT[0], "Cover", "Cover", nullptr);
61  IUFillText(&StatusT[1], "Light", "Light", nullptr);
62  IUFillText(&StatusT[2], "Motor", "Motor", nullptr);
63  IUFillText(&StatusT[3], "Heater", "Heater", nullptr);
64  IUFillTextVector(&StatusTP, StatusT, 4, getDeviceName(), "Status", "Status", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
65 
66  // Firmware version
67  IUFillText(&FirmwareT[0], "Version", "Version", nullptr);
68  IUFillTextVector(&FirmwareTP, FirmwareT, 1, getDeviceName(), "Firmware", "Firmware", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
69 
72 
73  LightIntensityN[0].min = 0;
74  LightIntensityN[0].max = 4096;
75  LightIntensityN[0].step = 1;
76 
78 
80 
81  serialConnection = new Connection::Serial(this);
82  serialConnection->registerHandshake([&]()
83  {
84  return Handshake();
85  });
86  registerConnection(serialConnection);
88  return true;
89 }
90 
91 void DeepSkyDadFP1::ISGetProperties(const char *dev)
92 {
94 
95  // Get Light box properties
97 }
98 
100 {
102 
103  if (isConnected())
104  {
108  defineProperty(&HeaterModeSP);
109  defineProperty(&StatusTP);
110  defineProperty(&FirmwareTP);
111 
113 
114  getStartupData();
115  }
116  else
117  {
121  deleteProperty(HeaterModeSP.name);
122  deleteProperty(StatusTP.name);
123  deleteProperty(FirmwareTP.name);
124 
126  }
127 
128  return true;
129 }
130 
132 {
133  return "Deep Sky Dad FP1";
134 }
135 
136 bool DeepSkyDadFP1::Handshake()
137 {
138  PortFD = serialConnection->getPortFD();
139  if (!ping())
140  {
141  LOG_ERROR("Device ping failed.");
142  return false;
143  }
144 
146  syncDriverInfo();
147 
148  return true;
149 }
150 
151 bool DeepSkyDadFP1::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
152 {
153  if (processLightBoxNumber(dev, name, values, names, n))
154  return true;
155 
156  return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n);
157 }
158 
159 bool DeepSkyDadFP1::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
160 {
161  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
162  {
163  if (processLightBoxText(dev, name, texts, names, n))
164  return true;
165  }
166 
167  return INDI::DefaultDevice::ISNewText(dev, name, texts, names, n);
168 }
169 
170 bool DeepSkyDadFP1::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
171 {
172  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
173  {
174  if (processDustCapSwitch(dev, name, states, names, n))
175  return true;
176 
177  if (processLightBoxSwitch(dev, name, states, names, n))
178  return true;
179 
180  if (strcmp(HeaterModeSP.name, name) == 0)
181  {
182  int current_mode = IUFindOnSwitchIndex(&HeaterModeSP);
183 
184  IUUpdateSwitch(&HeaterModeSP, states, names, n);
185 
186  int target_mode = IUFindOnSwitchIndex(&HeaterModeSP);
187 
188  if (current_mode == target_mode)
189  {
190  HeaterModeSP.s = IPS_OK;
191  IDSetSwitch(&HeaterModeSP, nullptr);
192  return true;
193  }
194 
195  char cmd[FLAT_RES] = {0};
196  char response[FLAT_RES] = {0};
197 
198  snprintf(cmd, FLAT_RES, "[SHTM%d]", target_mode);
199  bool rc = sendCommand(cmd, response);
200  if (!rc)
201  {
202  IUResetSwitch(&HeaterModeSP);
203  HeaterModeS[current_mode].s = ISS_ON;
204  HeaterModeSP.s = IPS_ALERT;
205  IDSetSwitch(&HeaterModeSP, nullptr);
206  return false;
207  }
208 
209  HeaterModeSP.s = IPS_OK;
210  IDSetSwitch(&HeaterModeSP, nullptr);
211  return true;
212  }
213  }
214 
215  return INDI::DefaultDevice::ISNewSwitch(dev, name, states, names, n);
216 }
217 
219 {
220  snoopLightBox(root);
221 
223 }
224 
226 {
228 
229  IUSaveConfigSwitch(fp, &HeaterModeSP);
230 
231  return saveLightBoxConfigItems(fp);
232 }
233 
234 bool DeepSkyDadFP1::ping()
235 {
236  char response[FLAT_RES] = {0};
237 
238  if (!sendCommand("[GPOS]", response))
239  return false;
240 
241  return true;
242 }
243 
245 {
246  if (!isConnected())
247  return;
248 
249  getStatus();
250 
252 }
253 
254 bool DeepSkyDadFP1::getStartupData()
255 {
256  bool rc1 = getFirmwareVersion();
257  bool rc2 = getStatus();
258  bool rc3 = getBrightness();
259 
260  return (rc1 && rc2 && rc3);
261 }
262 
264 {
265  char response[FLAT_RES];
266  if (!sendCommand("[STRG270]", response) || !sendCommand("[SMOV]", response))
267  return IPS_ALERT;
268 
269  if (strcmp(response, "(OK)") == 0)
270  {
271  // Set cover status to random value outside of range to force it to refresh
272  prevCoverStatus = 10;
273  return IPS_BUSY;
274  }
275  else
276  return IPS_ALERT;
277 }
278 
280 {
281  char response[FLAT_RES];
282  if (!sendCommand("[STRG0]", response) || !sendCommand("[SMOV]", response))
283  return IPS_ALERT;
284 
285  if (strcmp(response, "(OK)") == 0)
286  {
287  // Set cover status to random value outside of range to force it to refresh
288  prevCoverStatus = 10;
289  return IPS_BUSY;
290  }
291  else
292  return IPS_ALERT;
293 }
294 
296 {
297  char command[FLAT_CMD];
298  char response[FLAT_RES];
299 
300  if (enable)
301  strncpy(command, "[SLON1]", FLAT_CMD);
302  else
303  strncpy(command, "[SLON0]", FLAT_CMD);
304 
305  if (!sendCommand(command, response))
306  return false;
307 
308  if (strcmp(response, "(OK)") == 0)
309  return true;
310 
311  return false;
312 }
313 
314 bool DeepSkyDadFP1::getStatus()
315 {
316  char response[FLAT_RES];
317 
318  int motorStatus;
319  int lightStatus;
320  int coverStatus;
321  int heaterTemperature;
322  int heaterMode;
323 
324  if (!sendCommand("[GMOV]", response))
325  return false;
326  else
327  sscanf(response, "(%d)", &motorStatus);
328 
329  if (!sendCommand("[GLON]", response))
330  return false;
331  else
332  sscanf(response, "(%d)", &lightStatus);
333 
334  if (!sendCommand("[GPOS]", response))
335  return false;
336  else
337  sscanf(response, "(%d)", &coverStatus);
338 
339  if (!sendCommand("[GHTT]", response))
340  return false;
341  else
342  sscanf(response, "(%d)", &heaterTemperature);
343 
344  if (!sendCommand("[GHTM]", response))
345  return false;
346  else
347  sscanf(response, "(%d)", &heaterMode);
348 
349 
350  bool statusUpdated = false;
351 
352  if (coverStatus != prevCoverStatus)
353  {
354  if(motorStatus == 1)
355  {
356  if(coverStatus == 0)
357  {
358  IUSaveText(&StatusT[0], "Open");
359  }
360  else if(coverStatus == 270)
361  {
362  IUSaveText(&StatusT[0], "Closed");
363  }
364  else
365  {
366  IUSaveText(&StatusT[0], "Not open/closed");
367  }
368  }
369  else
370  {
371  prevCoverStatus = coverStatus;
372 
373  statusUpdated = true;
374 
375  if(coverStatus == 0)
376  {
377  IUSaveText(&StatusT[0], "Open");
378  if (ParkCapSP.s == IPS_BUSY || ParkCapSP.s == IPS_IDLE)
379  {
381  ParkCapS[0].s = ISS_OFF;
382  ParkCapS[1].s = ISS_ON;
383  ParkCapSP.s = IPS_OK;
384  LOG_INFO("Cover open.");
385  IDSetSwitch(&ParkCapSP, nullptr);
386  }
387  }
388  else if(coverStatus == 270)
389  {
390  IUSaveText(&StatusT[0], "Closed");
391  if (ParkCapSP.s == IPS_BUSY || ParkCapSP.s == IPS_IDLE)
392  {
394  ParkCapS[0].s = ISS_ON;
395  ParkCapS[1].s = ISS_OFF;
396  ParkCapSP.s = IPS_OK;
397  LOG_INFO("Cover closed.");
398  IDSetSwitch(&ParkCapSP, nullptr);
399  }
400  }
401  else
402  {
403  IUSaveText(&StatusT[0], "Not open/closed");
404  }
405  }
406  }
407 
408  if(motorStatus == 1)
409  {
410  IUSaveText(&StatusT[0], "Moving");
411  }
412 
413  if (lightStatus != prevLightStatus)
414  {
415  prevLightStatus = lightStatus;
416 
417  statusUpdated = true;
418 
419  switch (lightStatus)
420  {
421  case 0:
422  IUSaveText(&StatusT[1], "Off");
423  LightS[0].s = ISS_OFF;
424  LightS[1].s = ISS_ON;
425  IDSetSwitch(&LightSP, nullptr);
426  break;
427 
428  case 1:
429  IUSaveText(&StatusT[1], "On");
430  LightS[0].s = ISS_ON;
431  LightS[1].s = ISS_OFF;
432  IDSetSwitch(&LightSP, nullptr);
433  break;
434  }
435  }
436 
437  if (motorStatus != prevMotorStatus)
438  {
439  prevMotorStatus = motorStatus;
440 
441  statusUpdated = true;
442 
443  switch (motorStatus)
444  {
445  case 0:
446  IUSaveText(&StatusT[2], "Stopped");
447  break;
448 
449  case 1:
450  IUSaveText(&StatusT[2], "Running");
451  break;
452  }
453  }
454 
455  if (statusUpdated)
456  IDSetText(&StatusTP, nullptr);
457 
458  int heaterConnected = heaterTemperature > -40;
459  if(heaterConnected != prevHeaterConnected)
460  {
461  prevHeaterConnected = heaterConnected;
462  if(heaterConnected == 1)
463  {
464  IUSaveText(&StatusT[3], "Connected");
465  HeaterModeSP.s = IPS_OK;
466  }
467  else
468  {
469  HeaterModeSP.s = IPS_IDLE;
470  IUSaveText(&StatusT[3], "Disconnected");
471  }
472  }
473 
474  if(heaterMode != prevHeaterMode)
475  {
476  prevHeaterMode = heaterMode;
477  IUResetSwitch(&HeaterModeSP);
478  if(heaterMode == 0)
479  {
480  HeaterModeS[0].s = ISS_ON;
481  }
482  else if(heaterMode == 1)
483  {
484  HeaterModeS[1].s = ISS_ON;
485  }
486  else if(heaterMode == 2)
487  {
488  HeaterModeS[2].s = ISS_ON;
489  }
490  IDSetSwitch(&HeaterModeSP, nullptr);
491  }
492 
493  return true;
494 }
495 
496 bool DeepSkyDadFP1::getFirmwareVersion()
497 {
498  char response[FLAT_RES] = {0};
499  if (!sendCommand("[GFRM]", response))
500  return false;
501 
502  char versionString[6] = { 0 };
503  snprintf(versionString, 6, "%s", response + 31);
504  IUSaveText(&FirmwareT[0], response);
505  IDSetText(&FirmwareTP, nullptr);
506 
507  return true;
508 }
509 
510 bool DeepSkyDadFP1::getBrightness()
511 {
512  char response[FLAT_RES] = {0};
513  if (!sendCommand("[GLBR]", response))
514  return false;
515 
516  int32_t brightnessValue;
517  int rc = sscanf(response, "(%d)", &brightnessValue);
518 
519  if (rc <= 0)
520  {
521  LOGF_ERROR("Unable to parse brightness value (%s)", response);
522  return false;
523  }
524 
525  if (brightnessValue != prevBrightness)
526  {
527  prevBrightness = brightnessValue;
528  LightIntensityN[0].value = brightnessValue;
529  IDSetNumber(&LightIntensityNP, nullptr);
530  }
531 
532  return true;
533 }
534 
536 {
537  char command[FLAT_CMD] = {0};
538  char response[FLAT_RES] = {0};
539  snprintf(command, FLAT_CMD, "[SLBR%04d]", value);
540 
541  if (!sendCommand(command, response))
542  return false;
543 
544  if (strcmp(response, "(OK)") != 0)
545  {
546  LOGF_ERROR("Unable to set brightness value", response);
547  return false;
548  }
549 
550  return true;
551 }
552 
553 bool DeepSkyDadFP1::sendCommand(const char *cmd, char *res)
554 {
555  int nbytes_written = 0, nbytes_read = 0, rc = -1;
556 
557  tcflush(PortFD, TCIOFLUSH);
558 
559  LOGF_DEBUG("CMD <%s>", cmd);
560 
561  if ((rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
562  {
563  char errstr[MAXRBUF] = {0};
564  tty_error_msg(rc, errstr, MAXRBUF);
565  LOGF_ERROR("Serial write error: %s.", errstr);
566  return false;
567  }
568 
569  if (res == nullptr)
570  return true;
571 
572  if ((rc = tty_nread_section(PortFD, res, FLAT_RES, ')', FLAT_TIMEOUT, &nbytes_read)) != TTY_OK)
573  {
574  char errstr[MAXRBUF] = {0};
575  tty_error_msg(rc, errstr, MAXRBUF);
576  LOGF_ERROR("Serial read error: %s.", errstr);
577  return false;
578  }
579 
580  LOGF_DEBUG("RES <%s>", res);
581 
582  tcflush(PortFD, TCIOFLUSH);
583 
584  return true;
585 }
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
virtual bool SetLightBoxBrightness(uint16_t value) override
setBrightness Set light level. Must be impelemented in the child class, if supported.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool EnableLightBox(bool enable) override
EnableLightBox Turn on/off on a light box. Must be impelemented in the child class.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISSnoopDevice(XMLEle *root) override
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
virtual IPState UnParkCap() override
unPark dust cap (open cover). Must be implemented by child.
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual IPState ParkCap() override
Park dust cap (close cover). Must be implemented by child.
const char * getDefaultName() override
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function.
void syncDriverInfo()
syncDriverInfo sends the current driver information to the client.
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
void initDustCapProperties(const char *deviceName, const char *groupName)
Initilize dust cap properties. It is recommended to call this function within initProperties() of you...
bool processDustCapSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process dust cap switch properties.
ISwitchVectorProperty ParkCapSP
INumberVectorProperty LightIntensityNP
bool processLightBoxNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process light box number properties.
ISwitchVectorProperty LightSP
bool processLightBoxSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process light box switch properties.
void initLightBoxProperties(const char *deviceName, const char *groupNam)
Initilize light box properties. It is recommended to call this function within initProperties() of yo...
bool processLightBoxText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process light box text properties.
void isGetLightBoxProperties(const char *deviceName)
isGetLightBoxProperties Get light box properties
Provides interface to implement controllable light box/switch device.
#define FLAT_CMD
#define FLAT_TIMEOUT
#define FLAT_RES
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
IPState
Property state.
Definition: indiapi.h:160
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_1OFMANY
Definition: indiapi.h:173
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:474
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1167
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:666
Implementations for common driver routines.
@ TTY_OK
Definition: indicom.h:150
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indidevapi.c:25
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indidevapi.c:128
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indidevapi.c:148
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidevapi.c:291
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indidevapi.c:36
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition: indidevapi.c:158
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition: indidevapi.c:198
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidevapi.c:235
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
#define LOG_INFO(txt)
Definition: indilogger.h:74
#define MAXRBUF
Definition: indiserver.cpp:102
__u8 cmd[4]
Definition: pwc-ioctl.h:2
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371
char name[MAXINDINAME]
Definition: indiapi.h:250