1 #define USAGE \
2 "\n" \
3 "\nTest sending DiSEqC commands on a SAT frontend." \
4 "\n" \
5 "\nusage: FRONTEND=/dev/dvb/adapterX/frontendX diseqc [test_seq_no|'all']" \
6 "\n"
7 
8 #include <pthread.h>
9 #include <time.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <linux/dvb/frontend.h>
20 
21 
22 struct diseqc_cmd {
23 	struct dvb_diseqc_master_cmd cmd;
24 	uint32_t wait;
25 };
26 
27 
28 struct diseqc_cmd switch_cmds[] = {
29 	{ { { 0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00 }, 4 }, 0 },
30 	{ { { 0xe0, 0x10, 0x38, 0xf2, 0x00, 0x00 }, 4 }, 0 },
31 	{ { { 0xe0, 0x10, 0x38, 0xf1, 0x00, 0x00 }, 4 }, 0 },
32 	{ { { 0xe0, 0x10, 0x38, 0xf3, 0x00, 0x00 }, 4 }, 0 },
33 	{ { { 0xe0, 0x10, 0x38, 0xf4, 0x00, 0x00 }, 4 }, 0 },
34 	{ { { 0xe0, 0x10, 0x38, 0xf6, 0x00, 0x00 }, 4 }, 0 },
35 	{ { { 0xe0, 0x10, 0x38, 0xf5, 0x00, 0x00 }, 4 }, 0 },
36 	{ { { 0xe0, 0x10, 0x38, 0xf7, 0x00, 0x00 }, 4 }, 0 },
37 	{ { { 0xe0, 0x10, 0x38, 0xf8, 0x00, 0x00 }, 4 }, 0 },
38 	{ { { 0xe0, 0x10, 0x38, 0xfa, 0x00, 0x00 }, 4 }, 0 },
39 	{ { { 0xe0, 0x10, 0x38, 0xf9, 0x00, 0x00 }, 4 }, 0 },
40 	{ { { 0xe0, 0x10, 0x38, 0xfb, 0x00, 0x00 }, 4 }, 0 },
41 	{ { { 0xe0, 0x10, 0x38, 0xfc, 0x00, 0x00 }, 4 }, 0 },
42 	{ { { 0xe0, 0x10, 0x38, 0xfe, 0x00, 0x00 }, 4 }, 0 },
43 	{ { { 0xe0, 0x10, 0x38, 0xfd, 0x00, 0x00 }, 4 }, 0 },
44 	{ { { 0xe0, 0x10, 0x38, 0xff, 0x00, 0x00 }, 4 }, 0 }
45 };
46 
47 
48 /*--------------------------------------------------------------------------*/
49 
50 static inline
msleep(uint32_t msec)51 void msleep(uint32_t msec)
52 {
53 	struct timespec req = { msec / 1000, 1000000 * (msec % 1000) };
54 
55 	while (nanosleep(&req, &req))
56 		;
57 }
58 
59 
60 static
diseqc_send_msg(int fd,fe_sec_voltage_t v,struct diseqc_cmd ** cmd,fe_sec_tone_mode_t t,fe_sec_mini_cmd_t b)61 void diseqc_send_msg(int fd, fe_sec_voltage_t v, struct diseqc_cmd **cmd,
62 		     fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b)
63 {
64 	ioctl(fd, FE_SET_TONE, SEC_TONE_OFF);
65 	ioctl(fd, FE_SET_VOLTAGE, v);
66 
67 	msleep(15);
68 	while (*cmd) {
69 		printf("msg: %02x %02x %02x %02x %02x %02x\n",
70 		       (*cmd)->cmd.msg[0], (*cmd)->cmd.msg[1],
71 		       (*cmd)->cmd.msg[2], (*cmd)->cmd.msg[3],
72 		       (*cmd)->cmd.msg[4], (*cmd)->cmd.msg[5]);
73 
74 		ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &(*cmd)->cmd);
75 		msleep((*cmd)->wait);
76 		cmd++;
77 	}
78 
79 	printf("%s: ", __FUNCTION__);
80 
81 	printf(" %s ", v == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
82 	       v == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "???");
83 
84 	printf(" %s ", b == SEC_MINI_A ? "SEC_MINI_A" :
85 	       b == SEC_MINI_B ? "SEC_MINI_B" : "???");
86 
87 	printf(" %s\n", t == SEC_TONE_ON ? "SEC_TONE_ON" :
88 	       t == SEC_TONE_OFF ? "SEC_TONE_OFF" : "???");
89 
90 	msleep(15);
91 	ioctl(fd, FE_DISEQC_SEND_BURST, b);
92 
93 	msleep(15);
94 	ioctl(fd, FE_SET_TONE, t);
95 }
96 
97 
main(int argc,char ** argv)98 int main(int argc, char **argv)
99 {
100 	struct diseqc_cmd *cmd[2] = { NULL, NULL };
101 	char *fedev = "/dev/dvb/adapter0/frontend0";
102 	int fd;
103 
104 	if (getenv("FRONTEND"))
105 		fedev = getenv("FRONTEND");
106 
107 	printf("diseqc test: using '%s'\n", fedev);
108 
109 	if ((fd = open(fedev, O_RDWR)) < 0) {
110 		perror("open");
111 		return -1;
112 	}
113 
114 	if (argc != 2) {
115 	    fprintf (stderr, "usage: %s [number|'all']\n" USAGE, argv[0]);
116 	    return 1;
117 	} else if (strcmp(argv[1], "all")) {
118 		int i = atol(argv[1]);
119 		cmd[0] = &switch_cmds[i];
120 		diseqc_send_msg(fd,
121 				i % 2 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13,
122 				cmd,
123 				(i/2) % 2 ? SEC_TONE_ON : SEC_TONE_OFF,
124 				(i/4) % 2 ? SEC_MINI_B : SEC_MINI_A);
125 	} else {
126 		unsigned int j;
127 
128 		for (j=0; j<sizeof(switch_cmds)/sizeof(struct diseqc_cmd); j++)
129 		{
130 			cmd[0] = &switch_cmds[j];
131 			diseqc_send_msg(fd,
132 					j % 2 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13,
133 					cmd,
134 					(j/2) % 2 ? SEC_TONE_ON : SEC_TONE_OFF,
135 					(j/4) % 2 ? SEC_MINI_B : SEC_MINI_A);
136 			msleep (1000);
137 		}
138 	}
139 
140 	close(fd);
141 
142 	return 0;
143 }
144