arduino.c
4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <libusb-1.0/libusb.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include "arduino.h"
void init(libusb_context **context, libusb_device ***devices, ssize_t *devices_count){
int status = libusb_init(context);
if(status != 0){perror("libusb_init"); exit(-1);}
*devices_count = libusb_get_device_list(*context, devices);
if(*devices_count < 0){perror("libusb_get_device_list"); exit(-1);}
}
libusb_device* searchArduino(libusb_device **devices, ssize_t devices_count){
for(int i=0; i<devices_count; i++){
libusb_device *device = devices[i];
// device description
struct libusb_device_descriptor desc;
int status = libusb_get_device_descriptor(device, &desc);
if(status != 0) continue;
// search for device
if(desc.idVendor == ID_VENDOR
&& desc.idProduct == ID_PRODUCT)
return device;
}
return NULL;
}
void openConnection(libusb_device *arduino, libusb_device_handle **handle, struct libusb_config_descriptor **config_desc){
// open connection
int status = libusb_open(arduino, handle);
if(status != 0){ perror("libusb_open"); exit(-1); }
// prepare config
status = libusb_get_config_descriptor(arduino, 0, config_desc);
if(status != 0){ perror("libusb_get_config_descriptor"); exit(-1); }
int configuration = (*config_desc)->bConfigurationValue;
// detach kernel
for(int j=0; j<(*config_desc)->bNumInterfaces; j++){
int interface = (*config_desc)->interface[j].altsetting[0].bInterfaceNumber;
if(libusb_kernel_driver_active(*handle, interface)){
status = libusb_detach_kernel_driver(*handle, interface);
if(status != 0){ perror("libusb_detach_kernel_driver"); exit(-1); }
}
}
// use config
status = libusb_set_configuration(*handle, configuration);
if(status != 0){ perror("libusb_set_configuration"); exit(-1); }
// claim interfaces
for(int j=0; j<(*config_desc)->bNumInterfaces; j++){
struct libusb_interface_descriptor interface_desc = (*config_desc)->interface[j].altsetting[0];
int interface = interface_desc.bInterfaceNumber;
status = libusb_claim_interface(*handle, interface);
if(status != 0){ perror("libusb_claim_interface"); exit(-1); }
}
}
void getEndpoints(struct libusb_config_descriptor *config_desc, struct libusb_endpoint_descriptor *endpoint_desc_list){
int count = 0;
// in interfaces
for(int j=0; j<config_desc->bNumInterfaces; j++){
// find endpoints
for(int k=0; k<config_desc->interface[j].altsetting[0].bNumEndpoints; k++){
if(count > ENDPOINTS_NUMBER){ printf("getEndpoints: Array out of bound :%d:", count); exit(-1); }
*(endpoint_desc_list + count) = config_desc->interface[j].altsetting[0].endpoint[k];
count++;
}
}
//if(count != ENDPOINTS_NUMBER){ printf("Wrong number of endpoints.\nIs this the good device ?\n"); exit(-1); }
}
void start(libusb_context **context, libusb_device ***devices, libusb_device_handle **handle, struct libusb_config_descriptor **config_desc, struct libusb_endpoint_descriptor *endpoint_desc_list){
// init
ssize_t devices_count;
init(context, devices, &devices_count);
// get arduino device
libusb_device *arduino = searchArduino(*devices, devices_count);
if(arduino == NULL){ printf("Arduino device not found\n"); exit(-1); }
// open connection, use config, detach kernel and claim interfaces
openConnection(arduino, handle, config_desc);
// get enpoints
getEndpoints(*config_desc, endpoint_desc_list);
}
void stop(struct libusb_config_descriptor *config_desc, libusb_device_handle *handle, libusb_device **devices, libusb_context *context){
// release interfaces
for(int j=0; j<config_desc->bNumInterfaces; j++){
struct libusb_interface_descriptor interface_desc = config_desc->interface[j].altsetting[0];
int interface = interface_desc.bInterfaceNumber;
int status = libusb_release_interface(handle, interface);
if(status != 0){ perror("libusb_release_interface"); exit(-1); }
}
// free config
libusb_free_config_descriptor(config_desc);
// close connection
libusb_close(handle);
// free device list
libusb_free_device_list(devices, 1);
// libusb exit
libusb_exit(context);
}
void sendData(int endpoint_id, uint8_t data, libusb_device_handle *handle, struct libusb_endpoint_descriptor *endpoint_desc_list){
if(endpoint_id < 0 || endpoint_id > 1){ printf("(sendData) Wrong endpoint !\nMust be 0 or 1\n"); return; }
int status = libusb_interrupt_transfer(handle, endpoint_desc_list[endpoint_id].bEndpointAddress, (unsigned char *) &data, 1, NULL, TIMEOUT);
if(status!=0 && status!=LIBUSB_ERROR_TIMEOUT){ perror("libusb_interrupt_transfer"); exit(-1); }
}
int receiveData(int endpoint_id, uint8_t *data, libusb_device_handle *handle, struct libusb_endpoint_descriptor *endpoint_desc_list){
if(endpoint_id < 2 || endpoint_id > 3){ printf("(sendData) Wrong endpoint !\nMust be 2 or 3\n"); return -1; }
int status = libusb_interrupt_transfer(handle, endpoint_desc_list[endpoint_id].bEndpointAddress, (unsigned char *) data, 1, NULL, TIMEOUT);
if(status!=0 && status!=LIBUSB_ERROR_TIMEOUT){ perror("libusb_interrupt_transfer"); exit(-1); }
return status;
}