source: blaster/main.c @ 92f3772

Revision 92f3772, 8.6 KB checked in by Tarmo Kople <tarmo@…>, 5 years ago (diff)

+ fixes

  • Property mode set to 100644
Line 
1/*
2 * File:   main.c
3 * Author: Tarmo Kople <tarmo@irvoodoo.com>
4 *
5 * Simple cli program to use IRvoodoo blaster functionality.
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <libvcomm/vcomm.h>
12#include <unistd.h>
13#include <ctype.h>
14#include <fcntl.h>
15#include <sys/stat.h>
16#include "blaster.h"
17
18header_t evTable;   // Table with event names
19char dbname[256];   // buffer for database name (full path + file name)
20FILE *fd = NULL;    // database filehandle
21// IRvoodoo handle
22hid_device *vhandle;    // IRvoodoo handle
23
24/*
25 * Derive file name (OS dependent)
26 */
27#ifdef WIN32
28// For windows
29void getDatabase(char *dbfullpath){
30    char *path = getenv("APPDATA");
31    sprintf(dbfullpath, "%s\\blaster.dat", path);
32}
33#else
34// For Os X & Linux
35#include <pwd.h>
36void getDatabase(char *dbfullpath){
37    struct passwd *pw = getpwuid(getuid());
38    sprintf(dbfullpath, "%s/.blaster.dat", pw->pw_dir);
39}
40#endif
41// ==================
42
43/**
44 * @brief Display help message
45 */
46void usage(void) {
47    fprintf(stderr, "\nUsage: blaster [options]\n"
48            "Options:\n"
49            " -b <event name> Blast event\n"
50            " -n <event name> Add (record) new event\n"
51            " -d <event name> Delete event\n"
52            " -l List configured events\n\n");
53}
54
55/**
56 * Initialize blaster
57 *
58 * open connection to IRvoodoo
59 * open or create database
60 */
61void init() {
62    // open connection IRvoodoo
63    int resp;
64    if ((resp = Vopen(&vhandle, 0))) {
65        switch (resp) {
66        case ERR_DEV_NOT_FOUND:
67            fprintf(stderr, "Error: could not find IRvoodoo !\n");
68            break;
69        case ERR_OPEN_DEV:
70            fprintf(stderr,
71                    "Error: could not open IRvoodoo,\ncheck device permissions!\n");
72            break;
73        case ERR_ARGUMENT_ERROR:
74            fprintf(stderr, "Error: libvcomm argument error !\n");
75            break;
76        default:
77            fprintf(stderr, "Error: %d has occured !\n", resp);
78            break;
79        }
80        // give up
81        exit(EXIT_FAILURE);
82    }
83
84    if(access(dbname, R_OK|W_OK)){
85        creat(dbname, 0644);
86    }
87    fd = fopen(dbname, "rb+");
88    if (NULL == fd) {
89        fprintf(stderr, "\nError opening database: %s !\n", dbname);
90        exit(EXIT_FAILURE);
91    }
92
93    /*
94     * Check if new or existing file
95     */
96    unsigned int sz;
97    fseek(fd, 0, SEEK_END);
98    sz = ftell(fd);
99    fseek(fd, 0, SEEK_SET);
100    if(sz >= sizeof(evTable)){
101        // read evTable from file
102        int numbytes = fread(&evTable, 1, sizeof(evTable), fd);
103        if(numbytes != sizeof(evTable)){
104            fprintf(stderr, "File data format error !\n");
105            exit(EXIT_FAILURE);
106        }
107    }
108}
109
110/**
111 * Clean up, called automatically on exit
112 *
113 * Close IRvoodoo connection
114 * Close database file
115 */
116void uninit() {
117    if (vhandle) {
118        Vset_mode(&vhandle, REQ_SET_MODE_NORMAL);
119        Vclose(&vhandle);
120    }
121    if(fd){
122        fclose(fd);
123    }
124}
125
126/**
127 * Handle communication error.
128 * (just print error & exit with EXIT_FAILURE)
129 */
130void comm_err() {
131    fprintf(stderr, "Error: communication error !\n");
132    exit(EXIT_FAILURE);
133}
134
135/**
136 * @brief Find record number by event name
137 * @param evname Event name
138 * @return Record number
139 */
140int find_record(char *evname){
141    int eventNum;
142    for(eventNum = 0; eventNum < MAX_EVENTS; eventNum++){
143        if(!strcmp(evname, evTable.evntList[eventNum].eventName)) {
144            return eventNum;
145        }
146    }
147    return -1;
148}
149
150/**
151 * @brief Save IRframe to file
152 * @param evname Name for the saved IRframe
153 * @param irframe IRframe to save
154 */
155void save_event(char *evname, irframe_t *irframe){
156    int eventNum = -1;
157    eventNum = find_record(evname);
158
159    if(eventNum == -1){
160        // no existing event, find first free record
161        int n;
162        for(n = 0; n < MAX_EVENTS; n++){
163            if(evTable.evntList[n].eventName[0] == 0) {
164                eventNum = n;
165                break;  // found first free record
166            }
167        }
168    }
169
170    if(eventNum == -1){
171        fprintf(stderr, "Error, event database if full !\n");
172        exit(EXIT_FAILURE);
173    }
174
175    sprintf(evTable.evntList[eventNum].eventName, evname, "%s");
176    record_t record;
177    memcpy(&record.frameData, irframe, sizeof(irframe_t));
178    record.frameSettings.duty = 50;
179    record.frameSettings.freq = 38;
180    rewind(fd);
181    fwrite(&evTable, sizeof(evTable), 1, fd);
182    fseek(fd, sizeof(evTable) + sizeof(record_t) * eventNum ,0);
183    fwrite(&record, sizeof(record), 1, fd);
184    fclose(fd);
185    fd = NULL;
186}
187
188/**
189 * @brief Capture new event & add to database
190 * @param evname Name of the event
191 */
192void new_event(char *evname) {
193    /*
194     * Create new empty IRcode
195     */
196    ircode_t ircode;
197    memset(&ircode, 0, sizeof(ircode));
198
199    // disable output buffering (needed for capture process printing)
200    setbuf(stdout, NULL);
201    printf("Got event name: %s\n", evname);
202    /*
203     * Clear IRvoodoo's IRframe
204     */
205    if (Vclear_last(&vhandle))
206        comm_err();
207    /*
208     *  set mode to capture, we are tryng to capture raw data
209     */
210    Vset_mode(&vhandle, REQ_SET_MODE_CAPT);
211
212    /*
213     * Start capturing process.
214     * Stop on timeout.
215     */
216    printf("Waiting for IR data. Press button on the remote control now !!!\n");
217    irframe_t irframe;
218    int maxtryes = 3;
219    while (maxtryes--) {
220        printf(".");
221        sleep(1);
222    }
223    printf("\n");
224    Vget_irframe(&vhandle, &irframe);
225    if(irframe.num_pulses < 10){
226        fprintf(stderr, "Not enough IR data captured, please try again !\n");
227        exit(EXIT_FAILURE);
228    }
229    /*
230     * Success
231     */
232    printf("Got %d samples, looks good ! Saving event.\n", irframe.num_pulses);
233    save_event(evname, &irframe);
234    exit(EXIT_SUCCESS);
235}
236
237/**
238 * @brief List available event in database
239 */
240void list_events(){
241    int eventNum;
242    printf("\nConfigured events:\n");
243    for(eventNum = 0; eventNum < MAX_EVENTS; eventNum++){
244        if(evTable.evntList[eventNum].eventName[0] != 0) {
245            printf("\t%s\n", evTable.evntList[eventNum].eventName);
246        }
247    }
248    printf("\n");
249    exit(EXIT_SUCCESS);
250}
251
252/**
253 * @brief Delete event from database
254 * @param evname Name of the event
255 */
256void delete_event(char *evname){
257
258    int eventNum = find_record(evname);
259    if(eventNum >= 0){
260        memset(evTable.evntList[eventNum].eventName, 0x00, MAX_NAME_LEN);
261        rewind(fd);
262        fwrite(&evTable, sizeof(evTable), 1, fd);
263        printf("Event successfully deleted!\n");
264        exit(EXIT_SUCCESS);
265    }
266
267    fprintf(stderr, "Event not deleted, no such event!\n");
268    exit(EXIT_FAILURE);
269}
270
271/**
272 * @brief Blast IR event
273 * @param evname Name of the event
274 */
275void blast_event(char *evname){
276    int eventNum = find_record(evname);
277    if(eventNum >= 0){
278        record_t record;
279        fseek(fd, sizeof(evTable) + sizeof(record) * eventNum, 0);
280        if(fread(&record, 1, sizeof(record), fd) != sizeof(record)){
281            fprintf(stderr, "Database read error !\n");
282            exit(EXIT_FAILURE);
283        }
284
285        Vset_irframe(&vhandle, &record.frameData);
286        Vblast_irframe(&vhandle, record.frameSettings.freq, record.frameSettings.duty);
287
288        exit(EXIT_SUCCESS);
289    }
290    fprintf(stderr, "No such event to blast: %s\n", evname);
291    exit(EXIT_FAILURE);
292}
293
294/**
295 * @brief Check if event name valid (maxi name length)
296 *
297 * @param evname Event name
298 */
299void chkevname(char *evname){
300    if(strlen(evname)+1 > MAX_NAME_LEN){
301        printf("Event name too long, max length: %d\n", MAX_NAME_LEN);
302        exit(EXIT_FAILURE);
303    }
304}
305
306/**
307 * @brief Main program
308 *
309 * Parse command-line arguments, exec actions
310 *
311 * @param argc
312 * @param argv
313 * @return
314 */
315int main(int argc, char** argv) {
316
317    getDatabase(dbname); // set database name (OS dependent)
318    vhandle = NULL;
319    fd = NULL;
320    // set exit hook for cleanup
321    atexit(uninit);
322    init();
323    int c;
324    while ((c = getopt(argc, argv, "b:n:d:lh")) != -1)
325        switch (c) {
326        case 'b':
327            chkevname(optarg);
328            blast_event(optarg);
329            break;
330        case 'n':
331            chkevname(optarg);
332            new_event(optarg);
333            break;
334        case 'd':
335            chkevname(optarg);
336            delete_event(optarg);
337            break;
338        case 'l':
339            list_events();
340            break;
341        case 'h':
342            usage();
343            exit(EXIT_SUCCESS);
344            break;
345        case '?':
346            if (isprint(optopt))
347                fprintf(stderr, "Unknown option `-%c'.\n", optopt);
348            else
349                fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
350            break;
351        }
352    usage();
353    exit(EXIT_SUCCESS);
354}
Note: See TracBrowser for help on using the repository browser.