Difference between revisions of "Hardware driver API"

From sigrok
Jump to navigation Jump to search
m (Fixed typo)
 
(12 intermediate revisions by 4 users not shown)
Line 1: Line 1:
Every plugin is built as a shared library, dynamically loaded by the backend at startup. The plugin must define a structure as follows:
Every driver must define a '''struct sr_dev_driver''' to register it with libsigrok. It is defined as follows:


  #include "sigrok.h"
  struct sr_dev_driver {
    /* Driver-specific */
    char *name;
    char *longname;
    int api_version;
    int (*init) (void);
    int (*cleanup) (void);
    GSList *(*scan) (GSList *options);
    GSList *(*dev_list) (void);
    int (*dev_clear) (void);
   
   
struct device_plugin {
    /* Device-specific */
/* plugin-specific */
    int (*dev_open) (struct sr_dev_inst *sdi);
char *name;
    int (*dev_close) (struct sr_dev_inst *sdi);
int api_version;
    int (*config_get) (int info_id, const void **data,
int (*init) (char *deviceinfo);
            const struct sr_dev_inst *sdi);
void (*cleanup) (void);
    int (*config_set) (const struct sr_dev_inst *sdi, int hwcap,
            const void *value);
    int (*dev_acquisition_start) (const struct sr_dev_inst *sdi,
            void *cb_data);
    int (*dev_acquisition_stop) (struct sr_dev_inst *sdi,
            void *cb_data);
   
   
/* device-specific */
    /* Dynamic */
int (*open) (int device_index);
    void *priv;
void (*close) (int device_index);
char *(*get_device_info) (int device_index, int device_info_id);
int (*get_status) (int device_index);
int *(*get_capabilities) (void);
int (*set_configuration) (int device_index, int capability, char *value);
int (*start_acquisition) (int device_index, gpointer session_device_id);
void (*stop_acquisition) (int device_index, gpointer session_device_id);
  };
  };
#define SIGROK_HARDWARE_PLUGIN  struct device_plugin plugin_info


This structure is the only symbol imported into the backend namespace. The plugin's variables thus cannot conflict with the global sigrok namespace.
This structure should be the only symbol imported into the libsigrok namespace. The driver's variables thus cannot conflict with the global libsigrok namespace.
 
* '''name'''
<blockquote>
A short string describing this driver. It should contain only lowercase a-z, 0-9 and dashes (-). It will be referenced in saved session files.
</blockquote>
 
* '''longname'''
<blockquote>
A longer freeform string describing this driver. It will be shown to the user.
</blockquote>
 
* '''api_version'''
<blockquote>
Currently defined as 1.
</blockquote>
 
Most of the other members of the structure are pointers to driver callbacks:
 
* '''init()'''
<blockquote>
Called when the driver is initially loading into libsigrok, typically at program start.
<p>Returns SR_OK if successful, SR_ERR otherwise.</p>
</blockquote>
 
* '''cleanup()'''
<blockquote>
Called before the driver is unloaded. Any resources the driver holds must be released here, such as memory or connectivity library handles.
<p>Returns SR_OK if successful, SR_ERR otherwise.</p>
</blockquote>
 
* '''scan(GSList *options)'''
<blockquote>
When a frontend wants a driver to scan for devices on the system that it knows about, this function is called. If a device was found, any initialization it needs must be performed here; for example, uploading firmware should be done here.


* '''name'''<br />A string describing this driver. It will be referenced in saved session files.
A driver for USB-connected devices typically doesn't need any help with this: it will find devices known to it by their VendorID and ProductID (VID:PID).


* '''api_version'''<br />Currently defined as 1.
However other drivers &mdash; notably those which use a serial port  &mdash; need to be pointed at the device. The GSList <code>options</code> contains instances of this struct:


The other members of the structure are pointers to plugin callbacks:
<pre>
struct sr_hwopt {
    int hwopt;
    const void *value;
};
</pre>


* '''init(char *device)'''<br />Called when the plugin is initially loading into sigrok, typically at program start. The parameter refers to a device name or special file, whichever is applicable for the plugin. Devices which don't need a supplied device, such as USB devices, can simply ignore this parameter. The function returns the number of devices found, and 0 if no suitable device was found. If a device was found, any initialization it needs must be performed here; for example, uploading firmware should be done here.
There are currently two valid <code>hwopt</code> values: '''SR_HWOPT_CONN''', where the associated value contains a string pointing the driver at the resource it needs to connect to. Right now that means a serial port of the form <code>/dev/ttyUSB0</code> or <code>/dev/ttyACM0</code>. The second <code>hwopt</code> is '''SR_HWOPT_SERIALCOMM''', which defines the serial communication parameters for the given port in the form ''&lt;baudrate&gt;/&lt;data bits&gt;&lt;parity&gt;&lt;stop bits&gt;'', for example "9600/8n1" or "600/7o2".


* '''cleanup()'''<br />Called before the plugin is unloaded. Release any resources the plugin might be holding.
For serial port-based drivers, '''SR_HWOPT_CONN''' is always required, and '''SR_HWOPT_SERIALCOMM''' always optional: the driver should know at which bitrate its device(s) can communicate, or probe for it.


* '''open(int device_index)'''<br />Open the specified device. The device index starts at 0.
Any devices found must have a <code>struct sr_dev_inst</code> created, which is added to the driver's known instances -- a GSList stored in the driver context's <code>instances</code> field.


* '''close(int device_index)'''<br />Close the specified device.
A copy of the <code>struct sr_dev_inst</code> for every device found in the current invocation of <code>scan()</code> must also be returned in a GSList from the function itself; the frontend is responsible for freeing the list (but will not touch the instances it contains).


* '''get_device_info(int device_index, int device_info_id)'''<br />Returns information about the given device. The type of information is given as device_info_id, one of a set of defined constants. The return value is always a pointer, which points to information specific to the id.
The instances thus returned to the frontend are central to the communication between the driver and the libsigrok frontend: every other callback function has an instance struct as a parameter.
** DI_INSTANCE: Returns a pointer to a [[Formats_and_structures#device_instances|struct sigrok_device_instance]].
</blockquote>
** DI_NUM_PROBES: The number of probes connected to this device (integer).
** DI_SAMPLERATES: Returns a pointer to a [[Formats_and_structures#Sample_rates|struct samplerates]].


* '''get_status(int device_index)'''<br />Returns an integer describing the status of the plugin's connection to a device. This may be one of the following:
* '''dev_list()'''
** ST_NOT_FOUND: The device was not found.
<blockquote>
** ST_INITIALIZING: The device was found, but is still initializing.
Called whenever the frontend needs a list of device instances the driver knows about. This should just return the <code>instances</code> field in the driver's context struct.
** ST_INACTIVE: The device is live, but not in use.
</blockquote>
** ST_ACTIVE: The device is currently in use.


* '''get_capabilities()'''<br />This function returns a zero-terminated integer array with the plugin's capabilities, in the form of a set of defined constants. Some of these are informative, and some can be used to configure the plugin (or its connected device). The capabilities tables below have an overview of all possible capabilities.
* '''dev_clear()'''<br />
<blockquote>
Clear the list of device instances the driver knows about. A frontend may call the <code>scan()</code> function multiple times to add to the driver's list of known devices, for example with a different serial port each time. If the frontend then wants to start over, it needs this function to clear the list.
<p>Returns SR_OK if successful, SR_ERR otherwise.</p>
</blockquote>


* '''set_configuration(int device_index, int capability, char *value)'''<br />This is used to configure the plugin and/or connected device. The capability is one of the constants returned from the get_capabilities() call. The value depends on the parameter that is to be configured.
* '''dev_open(struct sr_dev_inst *sdi)'''<br />
<blockquote>
Open the specified device.
<p>Returns SR_OK if successful, SR_ERR otherwise.</p>
</blockquote>


* '''start_acquisition(int device_index, gpointer session_device_id)'''<br />Start acquisition on the specified device. The session_device_id will be passed along with the data feed of this session, as the first parameter to session bus callbacks.
* '''dev_close(struct sr_dev_inst *sdi)'''<br />
<blockquote>
Close the specified device.
<p>Returns SR_OK if successful, SR_ERR otherwise.</p>
</blockquote>


* '''stop_acquisition(int device_index, gpointer session_device_id)'''<br />Stop acquisition on the specified device. This causes a DF_END packet to be sent to the sesion bus.
* '''config_get(int info_id, const void **data, struct sr_dev_inst *sdi)'''
<blockquote>
Returns information about the driver, or, if '''sdi''' is provided, that device instance. The type of information is given as info_id, one of a set of defined constants. The return value is always a pointer which refers to information specific to the id. Check <code>libsigrok.h</code> for the definitions ('''SR_DI_*''').
</blockquote>


== Device classes ==
* '''config_set(const struct sr_dev_inst *sdi, int hwcap, const void *value)'''
<blockquote>
This is used to configure the driver and/or connected device. The hwcap parameter is one of the constants returned from calling <code>info_get()</code> with either SR_DI_HWOPTS (driver options) or SR_DI_HWCAPS (device instance options) as the <code>info_id</code>. The value depends on the parameter to be configured.
</blockquote>


* HWCAP_LOGIC_ANALYZER
* '''dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)'''
: This device is a logic analyzer.
<blockquote>
Start acquisition on the specified device. The cb_data parameter will be passed along with the data feed of this session, as the first parameter to session bus callbacks.
</blockquote>


== Device options ==
* '''dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_data)'''
<blockquote>
Stop acquisition on the specified device. This causes a DF_END packet to be sent to the session bus.
</blockquote>


* HWCAP_SAMPLERATE
* '''priv'''
: The sample rate in Hz (uint64_t *).
<blockquote>
* HWCAP_PROBECONFIG
This should contain a pointer to a <code>struct drv_context</code>, which is initialized by the <code>init()</code> function.
: Probe configuration (GSList *probes)
</blockquote>
* HWCAP_CAPTURE_RATIO
: Pre-trigger capture ratio, as a percentage of the number of samples returned. The default is 0, meaning capturing only starts after the trigger fired  (uint64_t *).
* HWCAP_PATTERN_MODE
: Pattern to generate  (char **).


== Acquisition modes ==


* HWCAP_LIMIT_MSEC
[[Category:APIs]]
: How long the acquisition should last, in ms (uint64_t).
* HWCAP_LIMIT_SAMPLES
: How many samples to acquire in the session (uint64_t).
* HWCAP_CONTINUOUS
: Device supports continuous sampling

Latest revision as of 11:13, 5 August 2014

Every driver must define a struct sr_dev_driver to register it with libsigrok. It is defined as follows:

struct sr_dev_driver {
   /* Driver-specific */
   char *name;
   char *longname;
   int api_version;
   int (*init) (void);
   int (*cleanup) (void);
   GSList *(*scan) (GSList *options);
   GSList *(*dev_list) (void);
   int (*dev_clear) (void);

   /* Device-specific */
   int (*dev_open) (struct sr_dev_inst *sdi);
   int (*dev_close) (struct sr_dev_inst *sdi);
   int (*config_get) (int info_id, const void **data,
           const struct sr_dev_inst *sdi);
   int (*config_set) (const struct sr_dev_inst *sdi, int hwcap,
           const void *value);
   int (*dev_acquisition_start) (const struct sr_dev_inst *sdi,
           void *cb_data);
   int (*dev_acquisition_stop) (struct sr_dev_inst *sdi,
           void *cb_data);

   /* Dynamic */
   void *priv;
};

This structure should be the only symbol imported into the libsigrok namespace. The driver's variables thus cannot conflict with the global libsigrok namespace.

  • name

A short string describing this driver. It should contain only lowercase a-z, 0-9 and dashes (-). It will be referenced in saved session files.

  • longname

A longer freeform string describing this driver. It will be shown to the user.

  • api_version

Currently defined as 1.

Most of the other members of the structure are pointers to driver callbacks:

  • init()

Called when the driver is initially loading into libsigrok, typically at program start.

Returns SR_OK if successful, SR_ERR otherwise.

  • cleanup()

Called before the driver is unloaded. Any resources the driver holds must be released here, such as memory or connectivity library handles.

Returns SR_OK if successful, SR_ERR otherwise.

  • scan(GSList *options)

When a frontend wants a driver to scan for devices on the system that it knows about, this function is called. If a device was found, any initialization it needs must be performed here; for example, uploading firmware should be done here.

A driver for USB-connected devices typically doesn't need any help with this: it will find devices known to it by their VendorID and ProductID (VID:PID).

However other drivers — notably those which use a serial port — need to be pointed at the device. The GSList options contains instances of this struct:

 struct sr_hwopt {
    int hwopt;
    const void *value;
 };

There are currently two valid hwopt values: SR_HWOPT_CONN, where the associated value contains a string pointing the driver at the resource it needs to connect to. Right now that means a serial port of the form /dev/ttyUSB0 or /dev/ttyACM0. The second hwopt is SR_HWOPT_SERIALCOMM, which defines the serial communication parameters for the given port in the form <baudrate>/<data bits><parity><stop bits>, for example "9600/8n1" or "600/7o2".

For serial port-based drivers, SR_HWOPT_CONN is always required, and SR_HWOPT_SERIALCOMM always optional: the driver should know at which bitrate its device(s) can communicate, or probe for it.

Any devices found must have a struct sr_dev_inst created, which is added to the driver's known instances -- a GSList stored in the driver context's instances field.

A copy of the struct sr_dev_inst for every device found in the current invocation of scan() must also be returned in a GSList from the function itself; the frontend is responsible for freeing the list (but will not touch the instances it contains).

The instances thus returned to the frontend are central to the communication between the driver and the libsigrok frontend: every other callback function has an instance struct as a parameter.

  • dev_list()

Called whenever the frontend needs a list of device instances the driver knows about. This should just return the instances field in the driver's context struct.

  • dev_clear()

Clear the list of device instances the driver knows about. A frontend may call the scan() function multiple times to add to the driver's list of known devices, for example with a different serial port each time. If the frontend then wants to start over, it needs this function to clear the list.

Returns SR_OK if successful, SR_ERR otherwise.

  • dev_open(struct sr_dev_inst *sdi)

Open the specified device.

Returns SR_OK if successful, SR_ERR otherwise.

  • dev_close(struct sr_dev_inst *sdi)

Close the specified device.

Returns SR_OK if successful, SR_ERR otherwise.

  • config_get(int info_id, const void **data, struct sr_dev_inst *sdi)

Returns information about the driver, or, if sdi is provided, that device instance. The type of information is given as info_id, one of a set of defined constants. The return value is always a pointer which refers to information specific to the id. Check libsigrok.h for the definitions (SR_DI_*).

  • config_set(const struct sr_dev_inst *sdi, int hwcap, const void *value)

This is used to configure the driver and/or connected device. The hwcap parameter is one of the constants returned from calling info_get() with either SR_DI_HWOPTS (driver options) or SR_DI_HWCAPS (device instance options) as the info_id. The value depends on the parameter to be configured.

  • dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)

Start acquisition on the specified device. The cb_data parameter will be passed along with the data feed of this session, as the first parameter to session bus callbacks.

  • dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_data)

Stop acquisition on the specified device. This causes a DF_END packet to be sent to the session bus.

  • priv

This should contain a pointer to a struct drv_context, which is initialized by the init() function.