Project

General

Profile

Download (17.1 KB) Statistics
| Branch: | Tag: | Revision:
1

    
2
/* (C) 2011-2012 by Harald Welte <laforge@gnumonks.org>
3
 *
4
 * All Rights Reserved
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
#include <stdlib.h>
21
#include <stdint.h>
22
#include <errno.h>
23

    
24
#include <board.h>
25
#include <utility/trace.h>
26
#include <utility/led.h>
27

    
28
#include <usb/common/core/USBGenericRequest.h>
29
#include <usb/device/core/USBD.h>
30
#include <usb/device/core/USBDDriver.h>
31
#include <usb/device/core/USBDDriverDescriptors.h>
32
#include <usb/device/core/USBDCallbacks.h>
33
#include <usb/common/audio/AUDGenericRequest.h>
34
#include <usb/common/audio/AUDFeatureUnitRequest.h>
35
#include <usb/common/audio/AUDFeatureUnitDescriptor.h>
36
#include <common.h>
37

    
38
#include <fast_source_descr.h>
39
#include <fast_source.h>
40

    
41
#include <tuner_e4k.h>
42
#include <si570.h>
43
#include <osdr_fpga.h>
44

    
45
#define OSMOSDR_CTRL_WRITE 0x07
46
#define OSMOSDR_CTRL_READ 0x87
47

    
48
extern const USBDDriverDescriptors auddFastSourceDriverDescriptors;
49
unsigned char fastsource_interfaces[3];
50
static USBDDriver fast_source_driver;
51

    
52
struct rctx_stats {
53
	uint32_t total;		/* total number of samples */
54
	uint32_t sum_ffff;	/* samples with I+Q = 0xffff */
55
	uint32_t sum_fffe;	/* samples with I+Q = 0xfffe */
56
	uint32_t sum_other;	/* samples with I+Q = something else */
57

    
58
	uint32_t delta_1;	/* delta of last I to current I == 1 */
59
	uint32_t delta_2;
60
	uint32_t delta_3;
61
	uint32_t delta_other;
62
};
63

    
64
struct usb_state {
65
	struct llist_head queue;
66
	int active;
67
	uint8_t muted;
68
#ifdef FPGA_TEST_STATS
69
	struct rctx_stats stats;
70
#endif
71
};
72
static struct usb_state usb_state;
73

    
74
#define EP_NR 6
75

    
76
static void fastsource_get_feat_cur_val(uint8_t entity, uint8_t channel,
77
				   uint8_t control, uint8_t length)
78
{
79
	TRACE_INFO("get_feat(E%u, CN%u, CS%u, L%u) ", entity, channel, control, length);
80
	if (channel == 0 && control == AUDFeatureUnitDescriptor_MUTE && length == 1)
81
		USBD_Write(0, &usb_state.muted, sizeof(usb_state.muted), 0, 0);
82
	else
83
		USBD_Stall(0);
84
}
85

    
86
static void fastsource_set_feat_cur_val(uint8_t entity, uint8_t channel,
87
				   uint8_t control, uint8_t length)
88
{
89
	TRACE_INFO("set_feat(E%u, CO%u, CH%u, L%u) ", entity, channel, control, length);
90
	if (channel == 0 && control == AUDFeatureUnitDescriptor_MUTE && length == 1)
91
		USBD_Read(0, &usb_state.muted, sizeof(usb_state.muted), 0, 0);
92
	else
93
		USBD_Stall(0);
94
}
95

    
96
static void handle_osmosdr_read(const USBGenericRequest* request)
97
{
98
	int len = USBGenericRequest_GetLength(request);
99
	printf("OsmoSDR GET request: type:%d, request:%d, value:%d, index: %d, length: %d\n\r",
100
		USBGenericRequest_GetType(request),
101
		USBGenericRequest_GetRequest(request),
102
		USBGenericRequest_GetValue(request),
103
		USBGenericRequest_GetIndex(request),
104
		len);
105
	USBD_Stall(0);
106
}
107

    
108
static uint32_t read_bytewise32(const uint8_t* data)
109
{
110
	return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
111
}
112

    
113
static uint16_t read_bytewise16(const uint8_t* data)
114
{
115
	return (data[0] << 8) | data[1];
116
}
117

    
118
typedef struct Request_ {
119
	uint16_t func;
120
	uint16_t len;
121
} Request;
122

    
123
#define FUNC(group, function) ((group << 8) | function)
124

    
125
#define GROUP_GENERAL 0x00
126
#define GROUP_FPGA_V2 0x01
127
#define GROUP_VCXO_SI570 0x02
128
#define GROUP_TUNER_E4K 0x03
129

    
130
const static Request g_writeRequests[] = {
131
	// general api
132
	{ FUNC(GROUP_GENERAL, 0x00), 0 }, // init whatever
133
	{ FUNC(GROUP_GENERAL, 0x01), 0 }, // power down
134
	{ FUNC(GROUP_GENERAL, 0x02), 0 }, // power up
135

    
136
	// fpga commands
137
	{ FUNC(GROUP_FPGA_V2, 0x00), 0 }, // fpga init
138
	{ FUNC(GROUP_FPGA_V2, 0x01), 5 }, // osdr_fpga_reg_write(uint8_t reg, uint32_t val)
139
	{ FUNC(GROUP_FPGA_V2, 0x02), 1 }, // osdr_fpga_set_decimation(uint8_t val)
140
	{ FUNC(GROUP_FPGA_V2, 0x03), 1 }, // osdr_fpga_set_iq_swap(uint8_t val)
141
	{ FUNC(GROUP_FPGA_V2, 0x04), 4 }, // osdr_fpga_set_iq_gain(uint16_t igain, uint16_t qgain)
142
	{ FUNC(GROUP_FPGA_V2, 0x05), 4 }, // osdr_fpga_set_iq_ofs(int16_t iofs, int16_t qofs)
143

    
144
	// si570 vcxo commads
145
	{ FUNC(GROUP_VCXO_SI570, 0x00), 0 }, // si570_init()
146
	{ FUNC(GROUP_VCXO_SI570, 0x01), 16 }, // si570_reg_write
147
	{ FUNC(GROUP_VCXO_SI570, 0x02), 8 }, // si570_set_freq(uint32_t freq, int trim);
148

    
149
	// e4000 tuner commands
150
	{ FUNC(GROUP_TUNER_E4K, 0x00), 0 }, // e4k_init()
151
	{ FUNC(GROUP_TUNER_E4K, 0x01), 0 }, // reg write
152
	{ FUNC(GROUP_TUNER_E4K, 0x02), 5 }, // e4k_if_gain_set(uint8_t stage, int8_t value)
153
	{ FUNC(GROUP_TUNER_E4K, 0x03), 1 }, // e4k_mixer_gain_set(struct e4k_state *e4k, int8_t value)
154
	{ FUNC(GROUP_TUNER_E4K, 0x04), 1 }, // e4k_commonmode_set(int8_t value)
155
	{ FUNC(GROUP_TUNER_E4K, 0x05), 4 }, // e4k_tune_freq(uint32_t freq)
156
	{ FUNC(GROUP_TUNER_E4K, 0x06), 5 }, // e4k_if_filter_bw_set(enum e4k_if_filter filter, uint32_t bandwidth)
157
	{ FUNC(GROUP_TUNER_E4K, 0x07), 1 }, // e4k_if_filter_chan_enable(int on)
158
	{ FUNC(GROUP_TUNER_E4K, 0x08), 4 }, // e4k_manual_dc_offset(int8_t iofs, int8_t irange, int8_t qofs, int8_t qrange)
159
	{ FUNC(GROUP_TUNER_E4K, 0x09), 0 }, // e4k_dc_offset_calibrate()
160
	{ FUNC(GROUP_TUNER_E4K, 0x0a), 0 }, // e4k_dc_offset_gen_table()
161
	{ FUNC(GROUP_TUNER_E4K, 0x0b), 4 }, // e4k_set_lna_gain(int32_t gain)
162
	{ FUNC(GROUP_TUNER_E4K, 0x0c), 1 }, // e4k_enable_manual_gain(uint8_t manual)
163
	{ FUNC(GROUP_TUNER_E4K, 0x0d), 4 }, // e4k_set_enh_gain(int32_t gain)
164
};
165

    
166
typedef struct WriteState_ {
167
	uint8_t data[16];
168
	uint16_t func;
169
} WriteState;
170

    
171
static WriteState g_writeState;
172
extern struct e4k_state e4k;
173
extern struct si570_ctx si570;
174

    
175
static void finalize_write(void *pArg, unsigned char status, unsigned int transferred, unsigned int remaining)
176
{
177
	int res;
178

    
179
	if((status != 0) ||(remaining != 0)) {
180
		USBD_Stall(0);
181
		return;
182
	}
183

    
184
	printf("Func: %04x ...", g_writeState.func);
185

    
186
	switch(g_writeState.func) {
187
		// general api
188
		case FUNC(GROUP_GENERAL, 0x00): // init all
189
			printf("general_init()");
190
			res = 0; // no op so far
191
			break;
192
		case FUNC(GROUP_GENERAL, 0x01): // power down
193
			printf("general_power_down()");
194
			osdr_fpga_power(0);
195
			sam3u_e4k_stby(&e4k, 1);
196
			sam3u_e4k_power(&e4k, 0);
197
			res = 0;
198
			break;
199
		case FUNC(GROUP_GENERAL, 0x02): // power up
200
			printf("general_power_up()");
201
			osdr_fpga_power(1);
202
			sam3u_e4k_power(&e4k, 1);
203
			sam3u_e4k_stby(&e4k, 0);
204
			res = 0;
205
			break;
206

    
207
		// fpga commands
208
		case FUNC(GROUP_FPGA_V2, 0x00): // fpga init
209
			printf("fpga_v2_init()");
210
			res = 0; // no op so far
211
			break;
212
		case FUNC(GROUP_FPGA_V2, 0x01):
213
			printf("fpga_v2_reg_write()");
214
			osdr_fpga_reg_write(g_writeState.data[0], read_bytewise32(g_writeState.data + 1));
215
			res = 0;
216
			break;
217
		case FUNC(GROUP_FPGA_V2, 0x02):
218
			printf("osdr_fpga_set_decimation()");
219
			osdr_fpga_set_decimation(g_writeState.data[0]);
220
			res = 0;
221
			break;
222
		case FUNC(GROUP_FPGA_V2, 0x03):
223
			printf("osdr_fpga_set_iq_swap()");
224
			osdr_fpga_set_iq_swap(g_writeState.data[0]);
225
			res = 0;
226
			break;
227
		case FUNC(GROUP_FPGA_V2, 0x04):
228
			printf("osdr_fpga_set_iq_gain()");
229
			osdr_fpga_set_iq_gain(read_bytewise16(g_writeState.data), read_bytewise16(g_writeState.data + 2));
230
			res = 0;
231
			break;
232
		case FUNC(GROUP_FPGA_V2, 0x05):
233
			printf("osdr_fpga_set_iq_ofs()");
234
			osdr_fpga_set_iq_ofs(read_bytewise16(g_writeState.data), read_bytewise16(g_writeState.data + 2));
235
			res = 0;
236
			break;
237

    
238
		// si570 vcxo commands
239
		case FUNC(GROUP_VCXO_SI570, 0x00): // si570_init()
240
			printf("si570_init()");
241
			res = si570_reinit(&si570);
242
			break;
243
		case FUNC(GROUP_VCXO_SI570, 0x01):
244
			printf("si570_reg_write()");
245
			res = si570_reg_write(&si570, g_writeState.data[0], g_writeState.data[1], g_writeState.data + 2);
246
			break;
247
		case FUNC(GROUP_VCXO_SI570, 0x02):
248
			printf("si570_set_freq()");
249
			res = si570_set_freq(&si570, read_bytewise32(g_writeState.data), read_bytewise32(g_writeState.data + 4));
250
			break;
251

    
252
		// e4000 tuner commands
253
		case FUNC(GROUP_TUNER_E4K, 0x00):
254
			printf("e4k_init()");
255
			res = e4k_init(&e4k);
256
			break;
257
		case FUNC(GROUP_TUNER_E4K, 0x01): // reg write
258
			printf("e4k_reg_write()");
259
			res = -1;
260
			break;
261
		case FUNC(GROUP_TUNER_E4K, 0x02):
262
			printf("e4k_if_gain_set()");
263
			res = e4k_if_gain_set(&e4k, g_writeState.data[0], read_bytewise32(g_writeState.data + 1));
264
			break;
265
		case FUNC(GROUP_TUNER_E4K, 0x03):
266
			printf("e4k_mixer_gain_set()");
267
			res = e4k_mixer_gain_set(&e4k, g_writeState.data[0]);
268
			break;
269
		case FUNC(GROUP_TUNER_E4K, 0x04):
270
			printf("e4K_commonmode_set()");
271
			res = e4k_commonmode_set(&e4k, g_writeState.data[0]);
272
			break;
273
		case FUNC(GROUP_TUNER_E4K, 0x05):
274
			printf("e4k_tune_freq()");
275
			res = e4k_tune_freq(&e4k, read_bytewise32(g_writeState.data));
276
			break;
277
		case FUNC(GROUP_TUNER_E4K, 0x06):
278
			printf("e4k_if_filter_bw_set()");
279
			res = e4k_if_filter_bw_set(&e4k, g_writeState.data[0], read_bytewise32(g_writeState.data + 1));
280
			break;
281
		case FUNC(GROUP_TUNER_E4K, 0x07):
282
			printf("e4k_if_filter_chan_enable()");
283
			res = e4k_if_filter_chan_enable(&e4k, g_writeState.data[0]);
284
			break;
285
		case FUNC(GROUP_TUNER_E4K, 0x08):
286
			printf("e4k_manual_dc_offset()");
287
			res = e4k_manual_dc_offset(&e4k, g_writeState.data[0], g_writeState.data[1], g_writeState.data[2], g_writeState.data[3]);
288
			break;
289
		case FUNC(GROUP_TUNER_E4K, 0x09):
290
			printf("e4k_dc_offset_calibrate()");
291
			res = e4k_dc_offset_calibrate(&e4k);
292
			break;
293
		case FUNC(GROUP_TUNER_E4K, 0x0a):
294
			printf("e4k_dc_offset_gen_table()");
295
			res = e4k_dc_offset_gen_table(&e4k);
296
			break;
297
		case FUNC(GROUP_TUNER_E4K, 0x0b):
298
			printf("e4k_set_lna_gain()");
299
			res = e4k_set_lna_gain(&e4k, read_bytewise32(g_writeState.data));
300
			if(res == -EINVAL)
301
				res = -1;
302
			else res = 0;
303
			break;
304
		case FUNC(GROUP_TUNER_E4K, 0x0c):
305
			printf("e4k_enable_manual_gain()");
306
			res = e4k_enable_manual_gain(&e4k, g_writeState.data[0]);
307
			break;
308
		case FUNC(GROUP_TUNER_E4K, 0x0d):
309
			printf("e4k_set_enh_gain()");
310
			res = e4k_set_enh_gain(&e4k, read_bytewise32(g_writeState.data));
311
			break;
312

    
313
		default:
314
			res = -1;
315
			break;
316
	}
317

    
318
	printf(" res: %d\n\r", res);
319

    
320
	if(res == 0)
321
		USBD_Write(0, 0, 0, 0, 0);
322
	else USBD_Stall(0);
323
}
324

    
325
static void handle_osmosdr_write(const USBGenericRequest* request)
326
{
327
	uint16_t func = USBGenericRequest_GetValue(request);
328
	int len = USBGenericRequest_GetLength(request);
329
	int i;
330
/*
331
	printf("OsmoSDR SET request: type:%d, request:%d, value:%04x, index: %04x, length: %d\n\r",
332
		USBGenericRequest_GetType(request),
333
		USBGenericRequest_GetRequest(request),
334
		USBGenericRequest_GetValue(request),
335
		USBGenericRequest_GetIndex(request),
336
		len);
337
*/
338
	for(i = 0; i < ARRAY_SIZE(g_writeRequests); i++) {
339
		if(g_writeRequests[i].func == func)
340
			break;
341
	}
342
	if(i == ARRAY_SIZE(g_writeRequests)) {
343
		USBD_Stall(0);
344
		return;
345
	}
346
	if(len != g_writeRequests[i].len) {
347
		USBD_Stall(0);
348
		return;
349
	}
350

    
351
	g_writeState.func = func;
352

    
353
	if(len > 0)
354
		USBD_Read(0, g_writeState.data, len, finalize_write, 0);
355
	else finalize_write(NULL, 0, 0, 0);
356
}
357

    
358
/* handler for EP0 (control) requests */
359
void fastsource_req_hdlr(const USBGenericRequest *request)
360
{
361
	unsigned char entity;
362
	unsigned char interface;
363

    
364
	switch (USBGenericRequest_GetType(request)) {
365
	case USBGenericRequest_STANDARD:
366
		USBDDriver_RequestHandler(&fast_source_driver, request);
367
		return;
368
	case USBGenericRequest_CLASS:
369
		/* continue below */
370
		break;
371
	case USBGenericRequest_VENDOR:
372
		if(USBGenericRequest_GetRequest(request) == OSMOSDR_CTRL_WRITE)
373
			handle_osmosdr_write(request);
374
		else if(USBGenericRequest_GetRequest(request) == OSMOSDR_CTRL_READ)
375
			handle_osmosdr_read(request);
376
		else USBD_Stall(0);
377
		return;
378
	default:
379
		TRACE_WARNING("Unsupported request type %u\n\r",
380
				USBGenericRequest_GetType(request));
381
		USBD_Stall(0);
382
		return;
383
	}
384

    
385
	switch (USBGenericRequest_GetRequest(request)) {
386
	case AUDGenericRequest_SETCUR:
387
		entity = AUDGenericRequest_GetEntity(request);
388
		interface = AUDGenericRequest_GetInterface(request);
389
		if (((entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT) ||
390
		     (entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC)) &&
391
		    (interface == AUDDLoopRecDriverDescriptors_CONTROL)) {
392
			fastsource_set_feat_cur_val(entity,
393
				AUDFeatureUnitRequest_GetChannel(request),
394
				AUDFeatureUnitRequest_GetControl(request),
395
				USBGenericRequest_GetLength(request));
396
		} else {
397
			TRACE_WARNING("Unsupported entity/interface combination 0x%04x\n\r",
398
					USBGenericRequest_GetIndex(request));
399
			USBD_Stall(0);
400
		}
401
		break;
402
	case AUDGenericRequest_GETCUR:
403
		entity = AUDGenericRequest_GetEntity(request);
404
		interface = AUDGenericRequest_GetInterface(request);
405
		if (((entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT) ||
406
		     (entity == AUDDLoopRecDriverDescriptors_FEATUREUNIT_REC)) &&
407
		    (interface == AUDDLoopRecDriverDescriptors_CONTROL)) {
408
			fastsource_get_feat_cur_val(entity,
409
				AUDFeatureUnitRequest_GetChannel(request),
410
				AUDFeatureUnitRequest_GetControl(request),
411
				USBGenericRequest_GetLength(request));
412
		} else {
413
			TRACE_WARNING("Unsupported entity/interface combination 0x%04x\n\r",
414
					USBGenericRequest_GetIndex(request));
415
			USBD_Stall(0);
416
		}
417
		break;
418

    
419
	default:
420
		TRACE_WARNING("Unsupported request %u\n\r",
421
				USBGenericRequest_GetIndex(request));
422
		USBD_Stall(0);
423
		break;
424
	}
425
}
426

    
427
/* Initialize the driver */
428
void fastsource_init(void)
429
{
430
	memset(&usb_state, 0, sizeof(usb_state));
431
	memset(fastsource_interfaces, 0x00, sizeof(fastsource_interfaces));
432

    
433
	INIT_LLIST_HEAD(&usb_state.queue);
434

    
435
	USBDDriver_Initialize(&fast_source_driver, &auddFastSourceDriverDescriptors,
436
				fastsource_interfaces);
437

    
438
	USBD_Init();
439
}
440

    
441
static int refill_dma(void);
442

    
443
/* completion callback: USBD_Write() has completed an IN transfer */
444
static void wr_compl_cb(void *arg, unsigned char status, unsigned int transferred,
445
			unsigned int remain)
446
{
447
	struct req_ctx *rctx = arg;
448

    
449
	usb_state.active = 0;
450

    
451
	req_ctx_set_state(rctx, RCTX_STATE_FREE);
452

    
453
	if (status == 0 && remain == 0) {
454
		refill_dma();
455
	} else {
456
		TRACE_WARNING("Err: EP%u wr_compl, status 0x%02u, xfr %u, remain %u\r\n",
457
				EP_NR, status, transferred, remain);
458
	}
459
}
460

    
461
static int refill_dma(void)
462
{
463
	struct req_ctx *rctx;
464
	int res;
465

    
466
	rctx = req_ctx_dequeue(&usb_state.queue);
467
	if (!rctx) {
468
		//TRACE_WARNING("No rctx for re-filling USB DMA\n\r");
469
		usb_state.active = 0;
470
		return -ENOENT;
471
	}
472

    
473
	req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_BUSY);
474

    
475
	if ((res = USBD_Write(EP_NR, rctx->data, rctx->tot_len, wr_compl_cb, rctx)) != USBD_STATUS_SUCCESS) {
476
		TRACE_WARNING("USB EP busy while re-filling USB DMA: %d\n\r", res);
477
		req_ctx_set_state(rctx, RCTX_STATE_FREE);
478
		usb_state.active = 0;
479
		return -EBUSY;
480
	}
481

    
482
	usb_state.active = 1;
483
	return 0;
484
}
485

    
486
/* user API: requests us to start transmitting data via USB IN EP */
487
void fastsource_start(void)
488
{
489
	if(USBD_GetState() != USBD_STATE_CONFIGURED)
490
		return;
491

    
492
	if (!usb_state.active)
493
		refill_dma();
494
}
495

    
496
/* Use every Nth sample for computing statistics.  At fpga.adc_clkdiv=2 we can
497
 * still do every sample (NTH=1) at 20MHz SSC clock.  Above that, we have to look
498
 * at a sub-set only and thus increase NTH */
499
#define NTH	8
500

    
501
/* iterate over all samples in a given rctx and generate statistics */
502
static void rctx_stats_add(struct req_ctx *rctx, struct rctx_stats *s)
503
{
504
	uint16_t *data16;
505
	int inited = 0;
506

    
507
	//for (data16 = rctx->data; data16 < rctx->data + rctx->tot_len; data16 += 2) {
508
	for (data16 = rctx->data; data16 < rctx->data + rctx->tot_len; data16 += NTH*2) {
509
		uint32_t sum = data16[0] + data16[1];
510
		uint16_t diff_i, diff_q, last_i, last_q;
511

    
512
		s->total++;
513

    
514
		switch (sum) {
515
		case 0xFFFF:
516
			s->sum_ffff++;
517
			break;
518
		case 0xFFFE:
519
			s->sum_fffe++;
520
			break;
521
		default:
522
			s->sum_other++;
523
			break;
524
		}
525

    
526
		if (inited) {
527
			diff_i = (uint16_t)(last_i - data16[0]);
528
			diff_q = (uint16_t)(last_q - data16[0]);
529

    
530
			switch (diff_i) {
531
			case 1*NTH:
532
				s->delta_1++;
533
				break;
534
			case 2*NTH:
535
				s->delta_2++;
536
				break;
537
			case 3*NTH:
538
				s->delta_3++;
539
				break;
540
			default:
541
				s->delta_other++;
542
			}
543
		}
544

    
545
		inited = 1;
546
		last_i = data16[0];
547
		last_q = data16[1];
548
	}
549

    
550
	if (s->total > 0xFFFF) {
551
		printf("%u (f=%u/e=%u/o=%u) (1=%u/2=%u/3=%u/o=%u)\n\r",
552
			s->total, s->sum_ffff, s->sum_fffe, s->sum_other,
553
			s->delta_1, s->delta_2, s->delta_3, s->delta_other);
554
		memset(s, 0, sizeof(*s));
555
	}
556
}
557

    
558
/* SSC DMA informs us about completion of filling one rctx */
559
void usb_submit_req_ctx(struct req_ctx *rctx)
560
{
561
	req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
562

    
563
#ifdef FPGA_TEST_STATS
564
	rctx_stats_add(rctx, &usb_state.stats);
565
#endif
566
	//TRACE_INFO("USB rctx enqueue (%08x, %u/%u)\n\r", rctx, rctx->size, rctx->tot_len);
567
	req_ctx_enqueue(&usb_state.queue, rctx);
568

    
569
	fastsource_start();
570
}
571

    
572
/* callback */
573
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
574
{
575
	fastsource_req_hdlr(request);
576
}
577

    
578
void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
579
						 unsigned char setting)
580
{
581
	printf("USB_IF_CHANGED(%u, %u)\n\r", interface, setting);
582

    
583
	if ((interface == AUDDLoopRecDriverDescriptors_STREAMINGIN)
584
	    && (setting == 0))
585
		LED_Clear(USBD_LEDOTHER);
586
	else
587
		LED_Set(USBD_LEDOTHER);
588
}
589

    
590
void fastsource_dump(void)
591
{
592
	struct req_ctx *rctx, *rctx2;
593

    
594
	printf("usb pending:");
595
	llist_for_each_entry_safe(rctx, rctx2, &usb_state.queue, list)
596
		printf(" %02d", req_ctx_num(rctx));
597
	printf("\n\r");
598
}
(1-1/11)
Add picture from clipboard (Maximum size: 48.8 MB)