1#!/usr/bin/env python3

2# Copyright 2019 Canonical Ltd.

3# All rights reserved.

4#

5# Written by:

6# Jonathan Cave <jonathan.cave@canonical.com>

7

8 import errno

9 import os

10 import sys

11 import time

12

13

14 def export_gpio(lane):

15 try:

16 with open("/sys/class/gpio/export", "w") as f_export:

17 f_export.write("{}\n".format(lane))

18 except OSError as e:

19 if e.errno == errno.EBUSY:

20 # EBUSY indicates GPIO already exported

21 print("GPIO {} already exported".format(lane))

22 pass

23 else:

24 sys.stderr.write("Failed request to export GPIO {}\n".format(lane))

25 raise

26 # test directory exists

27 if not os.path.exists("/sys/class/gpio/gpio{}".format(lane)):

28 raise SystemExit("GPIO {} failed to export".format(lane))

29

30

31 def unexport_gpio(lane):

32 try:

33 with open("/sys/class/gpio/unexport", "w") as f_unexport:

34 f_unexport.write("{}\n".format(lane))

35 except OSError:

36 sys.stderr.write("Failed request to unexport GPIO {}\n".format(lane))

37 raise

38 # test directory removed

39 if os.path.exists("/sys/class/gpio/gpio{}".format(lane)):

40 raise SystemExit("GPIO {} failed to export".format(lane))

41

42

43 def configure_gpio(lane, direction):

44 with open("/sys/class/gpio/gpio{}/direction".format(lane), "wt") as f:

45 f.write("{}\n".format(direction))

46

47

48 def write_gpio(lane, val):

49 with open("/sys/class/gpio/gpio{}/value".format(lane), "wt") as f:

50 f.write("{}\n".format(val))

51

52

53 def read_gpio(lane):

54 with open("/sys/class/gpio/gpio{}/value".format(lane), "r") as f:

55 return f.read().strip()

56

57

58 def loopback_test(out_lane, in_lane):

59 print("{} -> {}".format(out_lane, in_lane), flush=True)

60 export_gpio(out_lane)

61 configure_gpio(out_lane, "out")

62 export_gpio(in_lane)

63 configure_gpio(in_lane, "in")

64 for i in range(6):

65 write_gpio(out_lane, i % 2)

66 time.sleep(0.5)

67 if read_gpio(in_lane) != str(i % 2):

68 raise SystemExit(

69 "Failed loopback test out: {} in: {}".format(out_lane, in_lane)

70 )

71 time.sleep(0.5)

72 unexport_gpio(out_lane)

73 unexport_gpio(in_lane)

74

75

76 def gpio_pairs(model_name):

77 gpio_data = os.path.expandvars(

78 "$PLAINBOX_PROVIDER_DATA/gpio-loopback.{}.in".format(model_name)

79 )

80 if not os.path.exists(gpio_data):

81 raise SystemExit(

82 "ERROR: no gpio information found at: {}".format(gpio_data)

83 )

84 with open(gpio_data, "r") as f:

85 for line in f:

86 if line.startswith("#"):

87 continue

88 yield line.strip().split(",")

89

90

91 def main():

92 if len(sys.argv) < 2:

93 raise SystemExit("Usage: gpio_syfs_loopback.py MODEL_NAME")

94 model_name = sys.argv[1]

95 for pair in gpio_pairs(model_name):

96 loopback_test(*pair)

97

98

99 if __name__ == "__main__":

100 main()