2828 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2929 * POSSIBILITY OF SUCH DAMAGE.
3030 */
31+ #define _GNU_SOURCE
3132#include <sys/socket.h>
3233#include <sys/types.h>
3334#include <arpa/inet.h>
3940#include <string.h>
4041#include <stdlib.h>
4142#include <unistd.h>
43+ #include <yaml.h>
4244
4345#include "cdba-server.h"
4446#include "device.h"
47+ #include "device_parser.h"
48+
49+ #define TOKEN_LENGTH 16384
50+ #define FTDI_INTERFACE_COUNT 4
4551
4652#include <ftdi.h>
4753
@@ -54,18 +60,27 @@ enum {
5460 GPIO_COUNT
5561};
5662
57- struct ftdi_gpio {
63+ struct ftdi_gpio_options {
5864 struct {
5965 char * description ;
60- unsigned int interface ;
66+ char * vendor ;
67+ char * product ;
68+ char * serial ;
69+ unsigned int index ;
70+ char * devicenode ;
6171 } ftdi ;
6272 struct {
6373 bool present ;
74+ unsigned int interface ;
6475 unsigned int offset ;
6576 bool active_low ;
6677 } gpios [GPIO_COUNT ];
67- struct ftdi_context * gpio ;
68- unsigned char gpio_lines ;
78+ };
79+
80+ struct ftdi_gpio {
81+ struct ftdi_gpio_options * options ;
82+ struct ftdi_context * interface [FTDI_INTERFACE_COUNT ];
83+ unsigned char gpio_lines [FTDI_INTERFACE_COUNT ];
6984};
7085
7186static int ftdi_gpio_device_power (struct ftdi_gpio * ftdi_gpio , bool on );
@@ -84,8 +99,9 @@ static int ftdi_gpio_toggle_io(struct ftdi_gpio *ftdi_gpio, unsigned int gpio, b
8499 * Example: s:0xVEND:0xPROD:SERIAL;D;POWER,0,ACTIVE_LOW;FASTBOOT_KEY,1,ACTIVE_HIGH;POWER_KEY,2,ACTIVE_HIGH;USB_DISCONNECT,3,ACTIVE_LOW
85100 */
86101
87- static void ftdi_gpio_parse_config (struct ftdi_gpio * ftdi_gpio , char * value )
102+ static void ftdi_gpio_parse_config (struct ftdi_gpio_options * options , char * value )
88103{
104+ unsigned ftdi_interface = 0 ;
89105 char * c , * interface ;
90106 size_t device_len ;
91107
@@ -96,7 +112,7 @@ static void ftdi_gpio_parse_config(struct ftdi_gpio *ftdi_gpio, char *value)
96112 else
97113 device_len = c - value ;
98114
99- ftdi_gpio -> ftdi .description = strndup (value , device_len );
115+ options -> ftdi .description = strndup (value , device_len );
100116
101117 if (!c )
102118 return ;
@@ -109,7 +125,7 @@ static void ftdi_gpio_parse_config(struct ftdi_gpio *ftdi_gpio, char *value)
109125 * interface != 'D' ) {
110126 errx (1 , "Invalid interface '%c'" , * interface );
111127 }
112- ftdi_gpio -> ftdi . interface = * interface - 'A' ;
128+ ftdi_interface = * interface - 'A' ;
113129
114130 c = strchr (interface , ';' );
115131
@@ -156,34 +172,167 @@ static void ftdi_gpio_parse_config(struct ftdi_gpio *ftdi_gpio, char *value)
156172 else
157173 errx (1 , "GPIOs polarity invalid: '%s'" , pol );
158174
159- ftdi_gpio -> gpios [gpio_type ].present = true;
160- ftdi_gpio -> gpios [gpio_type ].offset = gpio_offset ;
161- ftdi_gpio -> gpios [gpio_type ].active_low = active_low ;
175+ options -> gpios [gpio_type ].present = true;
176+ options -> gpios [gpio_type ].interface = ftdi_interface ;
177+ options -> gpios [gpio_type ].offset = gpio_offset ;
178+ options -> gpios [gpio_type ].active_low = active_low ;
162179 }
163180}
164181
182+ void * ftdi_gpio_parse_options (struct device_parser * dp )
183+ {
184+ struct ftdi_gpio_options * options ;
185+ char value [TOKEN_LENGTH ];
186+ char key [TOKEN_LENGTH ];
187+
188+ options = calloc (1 , sizeof (* options ));
189+
190+ /* Still accept legacy string */
191+ if (device_parser_accept (dp , YAML_SCALAR_EVENT , value , TOKEN_LENGTH )) {
192+ warnx ("Please switch to yaml config for ftdi_gpio configuration" );
193+ ftdi_gpio_parse_config (options , value );
194+ return options ;
195+ }
196+
197+ device_parser_accept (dp , YAML_MAPPING_START_EVENT , NULL , 0 );
198+
199+ while (device_parser_accept (dp , YAML_SCALAR_EVENT , key , TOKEN_LENGTH )) {
200+ unsigned int gpio_id ;
201+
202+ if (!strcmp (key , "power" )) {
203+ gpio_id = GPIO_POWER ;
204+ } else if (!strcmp (key , "fastboot_key" )) {
205+ gpio_id = GPIO_FASTBOOT_KEY ;
206+ } else if (!strcmp (key , "power_key" )) {
207+ gpio_id = GPIO_POWER_KEY ;
208+ } else if (!strcmp (key , "usb_disconnect" )) {
209+ gpio_id = GPIO_USB_DISCONNECT ;
210+ } else if (!strcmp (key , "output_enable" )) {
211+ gpio_id = GPIO_OUTPUT_ENABLE ;
212+ } else {
213+ if (!device_parser_accept (dp , YAML_SCALAR_EVENT , value , TOKEN_LENGTH ))
214+ errx (1 , "%s: expected value for \"%s\"" , __func__ , key );
215+
216+ if (!strcmp (key , "vendor" )) {
217+ options -> ftdi .vendor = strdup (value );
218+ } else if (!strcmp (key , "product" )) {
219+ options -> ftdi .product = strdup (value );
220+ } else if (!strcmp (key , "index" )) {
221+ options -> ftdi .index = strtoul (value , NULL , 0 );
222+ } else if (!strcmp (key , "serial" )) {
223+ options -> ftdi .serial = strdup (value );
224+ } else if (!strcmp (key , "devicenode" )) {
225+ options -> ftdi .devicenode = strdup (value );
226+ } else
227+ errx (1 , "%s: unknown type \"%s\"" , __func__ , key );
228+
229+ continue ;
230+ }
231+
232+ device_parser_expect (dp , YAML_MAPPING_START_EVENT , NULL , 0 );
233+
234+ while (device_parser_accept (dp , YAML_SCALAR_EVENT , key , TOKEN_LENGTH )) {
235+ device_parser_accept (dp , YAML_SCALAR_EVENT , value , TOKEN_LENGTH );
236+
237+ if (!strcmp (key , "line" )) {
238+ options -> gpios [gpio_id ].offset = strtoul (value , NULL , 0 );
239+ } else if (!strcmp (key , "interface" )) {
240+ if (* value != 'A' &&
241+ * value != 'B' &&
242+ * value != 'C' &&
243+ * value != 'D' ) {
244+ errx (1 , "Invalid interface '%c' for gpio %u" ,
245+ * value , gpio_id );
246+ }
247+ options -> gpios [gpio_id ].interface = * value - 'A' ;
248+ } else if (!strcmp (key , "active_low" )) {
249+ if (!strcmp (value , "true" ))
250+ options -> gpios [gpio_id ].active_low = true;
251+ } else {
252+ errx (1 , "%s: unknown option \"%s\"" , __func__ , key );
253+ exit (1 );
254+ }
255+ }
256+
257+ device_parser_expect (dp , YAML_MAPPING_END_EVENT , NULL , 0 );
258+
259+ options -> gpios [gpio_id ].present = true;
260+ }
261+
262+ device_parser_expect (dp , YAML_MAPPING_END_EVENT , NULL , 0 );
263+
264+ return options ;
265+ }
266+
165267static void * ftdi_gpio_open (struct device * dev )
166268{
167269 struct ftdi_gpio * ftdi_gpio ;
168- int ret ;
270+ int i , ret ;
169271
170272 ftdi_gpio = calloc (1 , sizeof (* ftdi_gpio ));
171273
172- ftdi_gpio_parse_config (ftdi_gpio , dev -> control_dev );
274+ ftdi_gpio -> options = dev -> control_options ;
275+
276+ /* Setup libftdi string */
277+ if (!ftdi_gpio -> options -> ftdi .description ) {
278+ if (ftdi_gpio -> options -> ftdi .devicenode )
279+ asprintf (& ftdi_gpio -> options -> ftdi .description ,
280+ "d:%s" , ftdi_gpio -> options -> ftdi .devicenode );
281+ else if (ftdi_gpio -> options -> ftdi .vendor &&
282+ ftdi_gpio -> options -> ftdi .product &&
283+ ftdi_gpio -> options -> ftdi .serial )
284+ asprintf (& ftdi_gpio -> options -> ftdi .description ,
285+ "s:%s:%s:%s" ,
286+ ftdi_gpio -> options -> ftdi .vendor ,
287+ ftdi_gpio -> options -> ftdi .product ,
288+ ftdi_gpio -> options -> ftdi .serial );
289+ else if (ftdi_gpio -> options -> ftdi .vendor &&
290+ ftdi_gpio -> options -> ftdi .product &&
291+ ftdi_gpio -> options -> ftdi .index > 0 )
292+ asprintf (& ftdi_gpio -> options -> ftdi .description ,
293+ "i:%s:%s:%u" ,
294+ ftdi_gpio -> options -> ftdi .vendor ,
295+ ftdi_gpio -> options -> ftdi .product ,
296+ ftdi_gpio -> options -> ftdi .index );
297+ else if (ftdi_gpio -> options -> ftdi .vendor &&
298+ ftdi_gpio -> options -> ftdi .product )
299+ asprintf (& ftdi_gpio -> options -> ftdi .description ,
300+ "i:%s:%s" ,
301+ ftdi_gpio -> options -> ftdi .vendor ,
302+ ftdi_gpio -> options -> ftdi .product );
303+ else
304+ errx (1 , "Incomplete FTDI description properties" );
305+ }
306+
307+ for (i = 0 ; i < GPIO_COUNT ; ++ i ) {
308+ unsigned int ftdi_interface ;
309+
310+ if (!ftdi_gpio -> options -> gpios [i ].present )
311+ continue ;
312+
313+ ftdi_interface = ftdi_gpio -> options -> gpios [i ].interface ;
173314
174- if ((ftdi_gpio -> gpio = ftdi_new ()) == 0 )
175- errx (1 , "failed to allocate ftdi gpio struct" );
315+ /* Skip if interface already opened */
316+ if (ftdi_gpio -> interface [ftdi_interface ])
317+ continue ;
176318
177- ftdi_set_interface (ftdi_gpio -> gpio , INTERFACE_A + ftdi_gpio -> ftdi .interface );
319+ if ((ftdi_gpio -> interface [ftdi_interface ] = ftdi_new ()) == 0 )
320+ errx (1 , "failed to allocate ftdi gpio struct" );
178321
179- ret = ftdi_usb_open_string (ftdi_gpio -> gpio , ftdi_gpio -> ftdi .description );
180- if (ret < 0 )
181- errx (1 , "failed to open ftdi gpio device '%s' (%d)" ,
182- ftdi_gpio -> ftdi .description , ret );
322+ ftdi_set_interface (ftdi_gpio -> interface [ftdi_interface ],
323+ INTERFACE_A + ftdi_interface );
183324
184- ftdi_set_bitmode (ftdi_gpio -> gpio , 0xFF , BITMODE_BITBANG );
325+ ret = ftdi_usb_open_string (ftdi_gpio -> interface [ftdi_interface ],
326+ ftdi_gpio -> options -> ftdi .description );
327+ if (ret < 0 )
328+ errx (1 , "failed to open ftdi gpio device '%s' (%d)" ,
329+ ftdi_gpio -> options -> ftdi .description , ret );
185330
186- if (ftdi_gpio -> gpios [GPIO_POWER_KEY ].present )
331+ ftdi_set_bitmode (ftdi_gpio -> interface [ftdi_interface ],
332+ 0xFF , BITMODE_BITBANG );
333+ }
334+
335+ if (ftdi_gpio -> options -> gpios [GPIO_POWER_KEY ].present )
187336 dev -> has_power_key = true;
188337
189338 ftdi_gpio_device_power (ftdi_gpio , 0 );
@@ -193,7 +342,7 @@ static void *ftdi_gpio_open(struct device *dev)
193342 else
194343 ftdi_gpio_device_usb (ftdi_gpio , 0 );
195344
196- if (ftdi_gpio -> gpio_present [GPIO_OUTPUT_ENABLE ])
345+ if (ftdi_gpio -> options -> gpios [GPIO_OUTPUT_ENABLE ]. present )
197346 ftdi_gpio_toggle_io (ftdi_gpio , GPIO_OUTPUT_ENABLE , 1 );
198347
199348 usleep (500000 );
@@ -203,22 +352,26 @@ static void *ftdi_gpio_open(struct device *dev)
203352
204353static int ftdi_gpio_toggle_io (struct ftdi_gpio * ftdi_gpio , unsigned int gpio , bool on )
205354{
355+ unsigned int ftdi_interface ;
206356 unsigned int bit ;
207357
208- if (!ftdi_gpio -> gpios [gpio ].present )
358+ if (!ftdi_gpio -> options -> gpios [gpio ].present )
209359 return - EINVAL ;
210360
211- bit = ftdi_gpio -> gpios [gpio ].offset ;
361+ ftdi_interface = ftdi_gpio -> options -> gpios [gpio ].interface ;
362+
363+ bit = ftdi_gpio -> options -> gpios [gpio ].offset ;
212364
213- if (ftdi_gpio -> gpios [gpio ].active_low )
365+ if (ftdi_gpio -> options -> gpios [gpio ].active_low )
214366 on = !on ;
215367
216368 if (on )
217- ftdi_gpio -> gpio_lines |= (1 << bit );
369+ ftdi_gpio -> gpio_lines [ ftdi_interface ] |= (1 << bit );
218370 else
219- ftdi_gpio -> gpio_lines &= ~(1 << bit );
371+ ftdi_gpio -> gpio_lines [ ftdi_interface ] &= ~(1 << bit );
220372
221- return ftdi_write_data (ftdi_gpio -> gpio , & ftdi_gpio -> gpio_lines , 1 );
373+ return ftdi_write_data (ftdi_gpio -> interface [ftdi_interface ],
374+ & ftdi_gpio -> gpio_lines [ftdi_interface ], 1 );
222375}
223376
224377static int ftdi_gpio_device_power (struct ftdi_gpio * ftdi_gpio , bool on )
@@ -260,6 +413,7 @@ static void ftdi_gpio_key(struct device *dev, int key, bool asserted)
260413}
261414
262415const struct control_ops ftdi_gpio_ops = {
416+ .parse_options = ftdi_gpio_parse_options ,
263417 .open = ftdi_gpio_open ,
264418 .power = ftdi_gpio_power ,
265419 .usb = ftdi_gpio_usb ,
0 commit comments