1cimport urh.dev.native.lib.chackrf as chackrf
2from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t
3from libc.stdlib cimport malloc
4import time
5
6from urh.util.Logger import logger
7
8TIMEOUT = 0.2
9
10cdef object f
11cdef int RUNNING = 0
12
13cdef int _c_callback_recv(chackrf.hackrf_transfer*transfer)  with gil:
14    global f, RUNNING
15    try:
16        (<object> f)(transfer.buffer[0:transfer.valid_length])
17        return RUNNING
18    except Exception as e:
19        logger.error("Cython-HackRF:" + str(e))
20        return -1
21
22cdef int _c_callback_send(chackrf.hackrf_transfer*transfer)  with gil:
23    global f, RUNNING
24    # tostring() is a compatibility (numpy<1.9) alias for tobytes(). Despite its name it returns bytes not strings.
25    cdef unsigned int i
26    cdef unsigned int valid_length = <unsigned int>transfer.valid_length
27    cdef unsigned char[:] data  = (<object> f)(valid_length)
28    cdef unsigned int loop_end = min(len(data), valid_length)
29
30    for i in range(0, loop_end):
31        transfer.buffer[i] = data[i]
32
33    for i in range(loop_end, valid_length):
34        transfer.buffer[i] = 0
35
36    # Need to return -1 on finish, otherwise stop_tx_mode hangs forever
37    # Furthermore, this leads to windows issue https://github.com/jopohl/urh/issues/360
38    return RUNNING
39
40cdef chackrf.hackrf_device*_c_device
41cdef int hackrf_success = chackrf.HACKRF_SUCCESS
42
43IF HACKRF_MULTI_DEVICE_SUPPORT == 1:
44    cpdef has_multi_device_support():
45        return True
46    cpdef open(str serial_number=""):
47        if not serial_number:
48            return chackrf.hackrf_open(&_c_device)
49
50        desired_serial = serial_number.encode('UTF-8')
51        c_desired_serial = <char *> desired_serial
52        return chackrf.hackrf_open_by_serial(c_desired_serial, &_c_device)
53    cpdef get_device_list():
54        init()
55        cdef chackrf.hackrf_device_list_t* device_list = chackrf.hackrf_device_list()
56
57        result = []
58        cdef int i
59        for i in range(device_list.devicecount):
60            serial_number = device_list.serial_numbers[i].decode("UTF-8")
61            result.append(serial_number)
62
63        chackrf.hackrf_device_list_free(device_list)
64        exit()
65        return result
66ELSE:
67    cpdef has_multi_device_support():
68        return False
69    cpdef open(str serial_number=""):
70        return chackrf.hackrf_open(&_c_device)
71    cpdef get_device_list():
72        return None
73
74cpdef int setup(str serial):
75    """
76    Convenience method for init + open. This one is used by HackRF class.
77    :return:
78    """
79    init()
80    return open(serial)
81
82cpdef int init():
83    return chackrf.hackrf_init()
84
85cpdef int exit():
86    return chackrf.hackrf_exit()
87
88cpdef int close():
89    return chackrf.hackrf_close(_c_device)
90
91cpdef int start_rx_mode(callback):
92    global f, RUNNING
93    RUNNING = 0
94    f = callback
95    return chackrf.hackrf_start_rx(_c_device, _c_callback_recv, NULL)
96
97cpdef int stop_rx_mode():
98    global RUNNING
99    RUNNING = -1
100    time.sleep(TIMEOUT)
101    return chackrf.hackrf_stop_rx(_c_device)
102
103cpdef int start_tx_mode(callback):
104    global f, RUNNING
105    RUNNING = 0
106    f = callback
107    return chackrf.hackrf_start_tx(_c_device, _c_callback_send, NULL)
108
109cpdef int stop_tx_mode():
110    global RUNNING
111    RUNNING = -1
112    time.sleep(TIMEOUT)
113    return chackrf.hackrf_stop_tx(_c_device)
114
115cpdef int set_freq(freq_hz):
116    time.sleep(TIMEOUT)
117    return chackrf.hackrf_set_freq(_c_device, freq_hz)
118
119cpdef is_streaming():
120    time.sleep(TIMEOUT)
121    ret = chackrf.hackrf_is_streaming(_c_device)
122    if ret == 1:
123        return True
124    else:
125        return False
126
127cpdef int set_amp_enable(value):
128    time.sleep(TIMEOUT)
129    cdef uint8_t val = 1 if value else 0
130    return chackrf.hackrf_set_amp_enable(_c_device, val)
131
132cpdef int set_rf_gain(value):
133    """ Enable or disable RF amplifier """
134    return set_amp_enable(value)
135
136cpdef int set_if_rx_gain(value):
137    """ Sets the LNA gain, in 8Db steps, maximum value of 40 """
138    time.sleep(TIMEOUT)
139    return chackrf.hackrf_set_lna_gain(_c_device, value)
140
141cpdef int set_if_tx_gain(value):
142    """ Sets the txvga gain, in 1db steps, maximum value of 47 """
143    time.sleep(TIMEOUT)
144    return chackrf.hackrf_set_txvga_gain(_c_device, value)
145
146cpdef int set_baseband_gain(value):
147    """ Sets the vga gain, in 2db steps, maximum value of 62 """
148    time.sleep(TIMEOUT)
149    return chackrf.hackrf_set_vga_gain(_c_device, value)
150
151cpdef int set_sample_rate(sample_rate):
152    time.sleep(TIMEOUT)
153    return chackrf.hackrf_set_sample_rate(_c_device, sample_rate)
154
155cpdef int set_bias_tee(on_or_off):
156    time.sleep(TIMEOUT)
157    cdef uint8_t bias_tee = 1 if on_or_off else 0
158    return chackrf.hackrf_set_antenna_enable(_c_device, bias_tee)
159
160cpdef int set_baseband_filter_bandwidth(bandwidth_hz):
161    time.sleep(TIMEOUT)
162    return chackrf.hackrf_set_baseband_filter_bandwidth(_c_device, bandwidth_hz)
163