1/*
2 *	Driver for USB Audio Device Class devices.
3 *	Copyright (c) 2009,10,12 S.Zharski <imker@gmx.li>
4 *	Distributed under the terms of the MIT license.
5 *
6 */
7
8
9#include "Stream.h"
10#include "Device.h"
11#include "Driver.h"
12#include "Settings.h"
13
14
15Stream::Stream(Device *device, size_t interface, usb_interface_list *List
16										/*, bool isInput, uint32 HWChannel*/)
17			:
18			AudioStreamingInterface(&device->AudioControl(), interface, List),
19			fDevice(device),
20			fStatus(B_NO_INIT),
21			fStreamEndpoint(0),
22			fIsRunning(false),
23			fArea(-1),
24			fDescriptors(0),
25			fDescriptorsCount(0),
26			fCurrentBuffer(0),
27			fStartingFrame(0),
28			fSamplesCount(0),
29			fProcessedBuffers(0)/*,
30			fBuffersPhysAddress(0)/ *,
31			fRealTime(0),
32			fFramesCount(0),
33			fBufferCycle(0)*/
34{
35
36}
37
38
39Stream::~Stream()
40{
41	delete_area(fArea);
42}
43
44
45status_t
46Stream::Init()
47{
48	// lookup alternate with maximal (ch * 100 + resolution)
49	uint16 maxChxRes = 0;
50	for (int i = 0; i < fAlternates.Count(); i++) {
51		if (fAlternates[i]->Interface() == 0) {
52			TRACE("Ignore alternate %d - zero interface description.\n", i);
53			continue;
54		}
55
56		if (fAlternates[i]->Format() == 0) {
57			TRACE("Ignore alternate %d - zero format description.\n", i);
58			continue;
59		}
60
61		if (fAlternates[i]->Format()->fFormatType != UAF_FORMAT_TYPE_I) {
62			TRACE("Ignore alternate %d - format type %#02x is not supported.\n",
63									i, fAlternates[i]->Format()->fFormatType);
64			continue;
65		}
66
67		switch (fAlternates[i]->Interface()->fFormatTag) {
68			case UAF_PCM:
69			case UAF_PCM8:
70			case UAF_IEEE_FLOAT:
71		//	case UAF_ALAW:
72		//	case UAF_MULAW:
73				break;
74			default:
75				TRACE("Ignore alternate %d - format %#04x is not supported.\n",
76									i, fAlternates[i]->Interface()->fFormatTag);
77			continue;
78		}
79
80		TypeIFormatDescriptor* format
81				= static_cast<TypeIFormatDescriptor*>(fAlternates[i]->Format());
82
83		if (fAlternates[i]->Interface()->fFormatTag == UAF_PCM) {
84			switch(format->fBitResolution) {
85				default:
86				TRACE("Ignore alternate %d - bit resolution %d "
87						"is not supported.\n", i, format->fBitResolution);
88					continue;
89				case 8: case 16: case 18: case 20: case 24: case 32:
90					break;
91			}
92		}
93
94		uint16 chxRes = format->fNumChannels * 100 + format->fBitResolution;
95		if (chxRes > maxChxRes) {
96			maxChxRes = chxRes;
97			fActiveAlternate = i;
98		}
99	}
100
101	if (maxChxRes <= 0) {
102		TRACE("No compatible alternate found. Stream initialization failed.\n");
103		return fStatus;
104	}
105	const ASEndpointDescriptor* endpoint = fAlternates[
106												fActiveAlternate]->Endpoint();
107	fIsInput = (endpoint->fEndpointAddress & USB_ENDPOINT_ADDR_DIR_IN)
108													== USB_ENDPOINT_ADDR_DIR_IN;
109	TRACE("Alternate %d selected!\n", fActiveAlternate);
110
111	TypeIFormatDescriptor* format
112		= static_cast<TypeIFormatDescriptor*>(fAlternates[
113												fActiveAlternate]->Format());
114
115	size_t bufferSize = format->fNumChannels * format->fSubframeSize;
116	TRACE("bufferSize:%d\n", bufferSize);
117
118	bufferSize *= kSamplesBufferSize;
119	TRACE("bufferSize:%d\n", bufferSize);
120
121	bufferSize *= (sizeof(usb_iso_packet_descriptor) + endpoint->fMaxPacketSize);
122	TRACE("bufferSize:%d\n", bufferSize);
123
124	bufferSize /= endpoint->fMaxPacketSize;
125	TRACE("bufferSize:%d\n", bufferSize);
126
127	bufferSize = (bufferSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1);
128	TRACE("bufferSize:%d\n", bufferSize);
129
130	fArea = create_area( (fIsInput) ? DRIVER_NAME "_record_area" :
131											DRIVER_NAME "_playback_area",
132								(void**)&fDescriptors, B_ANY_KERNEL_ADDRESS,
133									bufferSize, B_CONTIGUOUS,
134										B_READ_AREA | B_WRITE_AREA);
135	if (fArea < 0) {
136		TRACE_ALWAYS("Error of creating %#x - bytes size buffer area:%#010x\n",
137												bufferSize, fArea);
138		fStatus = fArea;
139		return fStatus;
140	}
141
142	physical_entry PhysEntry;
143	get_memory_map(fDescriptors, bufferSize, &PhysEntry, 1);
144
145	TRACE_ALWAYS("Created area id: "
146			"%d\naddress:%#010x[phys:%#010x]\nsize:%#010x\n",
147			fArea, fDescriptors, PhysEntry.address, bufferSize);
148
149	fDescriptorsCount = bufferSize;
150	fDescriptorsCount /= (sizeof(usb_iso_packet_descriptor)
151												+ endpoint->fMaxPacketSize);
152	fDescriptorsCount /= kSamplesBufferCount;
153	// we need same size buffers. round it!
154	fDescriptorsCount *= kSamplesBufferCount;
155
156	fSamplesCount = fDescriptorsCount * endpoint->fMaxPacketSize;
157	TRACE("samplesCount:%d\n", fSamplesCount);
158
159	fSamplesCount /= format->fNumChannels * format->fSubframeSize;
160	TRACE("samplesCount:%d\n", fSamplesCount);
161
162	for (size_t i = 0; i < fDescriptorsCount; i++) {
163		fDescriptors[i].request_length = endpoint->fMaxPacketSize;
164		fDescriptors[i].actual_length = 0;
165		fDescriptors[i].status = B_OK;
166	}
167
168/*	uint32* b = (uint32*)(fDescriptors + fDescriptorsCount);
169	for (size_t i = 0; i < fSamplesCount; i++) {
170		b[i] = i * 10;
171	}*/
172
173	TRACE_ALWAYS("Descriptors count:%d\nsample size:%d\nchannels:%d:%d\n",
174			fDescriptorsCount, format->fSubframeSize, format->fNumChannels,
175				sizeof(usb_iso_packet_descriptor));
176	return fStatus = B_OK;
177}
178
179
180status_t
181Stream::OnSetConfiguration(usb_device device,
182								const usb_configuration_info *config)
183{
184	if (config == NULL) {
185		TRACE_ALWAYS("NULL configuration. Not set.\n");
186		return B_ERROR;
187	}
188
189	usb_interface_info* interface
190					= &config->interface[fInterface].alt[fActiveAlternate];
191	if (interface == NULL) {
192		TRACE_ALWAYS("NULL interface. Not set.\n");
193		return B_ERROR;
194	}
195
196	/*status_t status =*/ gUSBModule->set_alt_interface(device, interface);
197	uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress;
198
199	for (size_t i = 0; i < interface->endpoint_count; i++) {
200		if (address == interface->endpoint[i].descr->endpoint_address) {
201			fStreamEndpoint = interface->endpoint[i].handle;
202			TRACE("%s Stream Endpoint [address %#04x] handle is: %#010x.\n",
203					fIsInput ? "Input" : "Output", address, fStreamEndpoint);
204			return B_OK;
205		}
206	}
207
208	TRACE("%s Stream Endpoint [address %#04x] was not found.\n",
209			fIsInput ? "Input" : "Output", address);
210	return B_ERROR;
211}
212
213
214status_t
215Stream::Start()
216{
217	status_t result = B_BUSY;
218	if (!fIsRunning) {
219		if (!fIsInput) {
220			// for (size_t i = 0; i < kSamplesBufferCount; i++)
221			//	result = _QueueNextTransfer(i);
222			// TODO
223			//	result = _QueueNextTransfer(0);
224			result = B_OK;
225		} else
226			result = B_OK;
227		fIsRunning = result == B_OK;
228	}
229	return result;
230}
231
232
233status_t
234Stream::Stop()
235{
236	if (fIsRunning) {
237		gUSBModule->cancel_queued_transfers(fStreamEndpoint);
238		fIsRunning = false;
239	}
240
241	return B_OK;
242}
243
244
245status_t
246Stream::_QueueNextTransfer(size_t queuedBuffer)
247{
248	TypeIFormatDescriptor* format
249		= static_cast<TypeIFormatDescriptor*>(fAlternates[
250												fActiveAlternate]->Format());
251
252	size_t bufferSize = format->fNumChannels * format->fSubframeSize;
253	bufferSize *= fSamplesCount / kSamplesBufferCount;
254
255	uint8* buffers = (uint8*)(fDescriptors + fDescriptorsCount);
256
257	size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
258
259	TRACE("buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n",
260			buffers + bufferSize * queuedBuffer, bufferSize,
261			fDescriptors + queuedBuffer * packetsCount, packetsCount);
262
263	return gUSBModule->queue_isochronous(fStreamEndpoint,
264			buffers + bufferSize * queuedBuffer, bufferSize,
265			fDescriptors + queuedBuffer * packetsCount, packetsCount,
266			NULL/*&fStartingFrame*/, USB_ISO_ASAP,
267			Stream::_TransferCallback, this);
268
269	return B_OK;
270}
271
272
273void
274Stream::_TransferCallback(void *cookie, int32 status, void *data,
275	uint32 actualLength)
276{
277	Stream *stream = (Stream *)cookie;
278
279	stream->fCurrentBuffer++;
280	if (stream->fCurrentBuffer >= kSamplesBufferCount) {
281		stream->fCurrentBuffer = 0;
282	}
283
284	stream->_DumpDescriptors();
285
286	stream->_DumpDescriptors();
287
288	/*
289	status_t result = stream->_QueueNextTransfer(stream->fCurrentBuffer);
290
291	if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount) {
292		TRACE_ALWAYS("Processed buffers overflow:%d\n", stream->fProcessedBuffers);
293	}
294*/
295	release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
296
297	// TRACE_ALWAYS("st:%#010x, len:%d -> %#010x\n", status, actualLength, result);
298	TRACE_ALWAYS("st:%#010x, data:%#010x, len:%d\n", status, data, actualLength);
299
300/*	if (status != B_OK) {
301		TRACE_ALWAYS("Device status error:%#010x\n", status);
302		status_t result = gUSBModule->clear_feature(device->fControLeNDPOint,
303													USB_FEATURE_ENDPOINT_HALT);
304		if (result != B_OK)
305			TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", result);
306	}
307*/
308}
309
310
311void
312Stream::_DumpDescriptors()
313{
314	size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
315	size_t from = /*fCurrentBuffer > 0 ? packetsCount :*/ 0 ;
316	size_t to   = /*fCurrentBuffer > 0 ?*/ fDescriptorsCount /*: packetsCount*/ ;
317	for (size_t i = from; i < to; i++) {
318		TRACE_ALWAYS("%d:req_len:%d; act_len:%d; stat:%#010x\n", i,
319			fDescriptors[i].request_length,	fDescriptors[i].actual_length,
320			fDescriptors[i].status);
321	}
322}
323
324
325status_t
326Stream::GetEnabledChannels(uint32& offset, multi_channel_enable *Enable)
327{
328	AudioChannelCluster* cluster = ChannelCluster();
329	if (cluster == 0) {
330		return B_ERROR;
331	}
332
333	for (size_t i = 0; i < cluster->ChannelsCount(); i++) {
334		B_SET_CHANNEL(Enable->enable_bits, offset++, true);
335		TRACE("Report channel %d as enabled.\n", offset);
336	}
337
338	return B_OK;
339}
340
341
342status_t
343Stream::SetEnabledChannels(uint32& offset, multi_channel_enable *Enable)
344{
345	AudioChannelCluster* cluster = ChannelCluster();
346	if (cluster == 0) {
347		return B_ERROR;
348	}
349
350	for (size_t i = 0; i < cluster->ChannelsCount(); i++) {
351		TRACE("%s channel %d.\n", (B_TEST_CHANNEL(Enable->enable_bits, offset++)
352						? "Enable" : "Disable"), offset + 1);
353	}
354
355	return B_OK;
356}
357
358
359status_t
360Stream::GetGlobalFormat(multi_format_info *Format)
361{
362	if (IsInput()) {
363		// TODO
364		Format->input.rate = B_SR_48000;
365		Format->input.cvsr = 48000;
366		Format->input.format = B_FMT_16BIT;
367	} else {
368		// TODO
369		Format->output.rate = B_SR_48000;
370		Format->output.cvsr = 48000;
371		Format->output.format = B_FMT_16BIT;
372	}
373
374	return B_OK;
375}
376
377
378status_t
379Stream::SetGlobalFormat(multi_format_info *Format)
380{
381	if (IsInput()) {
382		// TODO
383		TRACE("input.rate:%d\n",		Format->input.rate);
384		TRACE("input.cvsr:%f\n",		Format->input.cvsr);
385		TRACE("input.format:%#08x\n",	Format->input.format);
386	} else {
387		// TODO
388		TRACE("output.rate:%d\n",		Format->output.rate);
389		TRACE("output.cvsr:%f\n",		Format->output.cvsr);
390		TRACE("output.format:%#08x\n",	Format->output.format);
391	}
392
393	return B_OK;
394}
395
396
397status_t
398Stream::GetBuffers(multi_buffer_list* List)
399{
400// TODO: check the available buffers count!
401
402	int32 startChannel = List->return_playback_channels;
403	buffer_desc** Buffers = List->playback_buffers;
404
405	if (fIsInput) {
406		List->flags |= B_MULTI_BUFFER_RECORD;
407		List->return_record_buffer_size = fSamplesCount / kSamplesBufferCount;
408		List->return_record_buffers = kSamplesBufferCount;
409		startChannel = List->return_record_channels;
410		Buffers = List->record_buffers;
411
412		TRACE("flags:%#10x\nreturn_record_buffer_size:%#010x\n"
413			"return_record_buffers:%#010x\n", List->flags,
414			List->return_record_buffer_size, List->return_record_buffers);
415	} else {
416		List->flags |= B_MULTI_BUFFER_PLAYBACK;
417		List->return_playback_buffer_size = fSamplesCount / kSamplesBufferCount;
418		List->return_playback_buffers = kSamplesBufferCount;
419
420		TRACE("flags:%#10x\nreturn_playback_buffer_size:%#010x\n"
421			"return_playback_buffers:%#010x\n", List->flags,
422			List->return_playback_buffer_size, List->return_playback_buffers);
423	}
424
425	TypeIFormatDescriptor* format
426		= static_cast<TypeIFormatDescriptor*>(
427						fAlternates[fActiveAlternate]->Format());
428	const ASEndpointDescriptor* endpoint
429					= fAlternates[fActiveAlternate]->Endpoint();
430
431	// [buffer][channel] init buffers
432	for (size_t buffer = 0; buffer < kSamplesBufferCount; buffer++) {
433		TRACE("%s buffer #%d:\n", fIsInput ? "input" : "output", buffer + 1);
434
435		for (size_t channel = startChannel;
436					channel < format->fNumChannels; channel++)
437		{
438			// init stride to the same for all buffers
439			uint32 stride = format->fSubframeSize * format->fNumChannels;
440			Buffers[buffer][channel].stride = stride;
441
442			// init to buffers area begin
443			Buffers[buffer][channel].base
444									= (char*)(fDescriptors + fDescriptorsCount);
445			// shift for whole buffer if required
446			size_t bufferSize = endpoint->fMaxPacketSize
447									* (fDescriptorsCount / kSamplesBufferCount);
448			Buffers[buffer][channel].base += buffer * bufferSize;
449			// shift for channel if required
450			Buffers[buffer][channel].base += channel * format->fSubframeSize;
451
452			TRACE("%d:%d: base:%#010x; stride:%#010x\n", buffer, channel,
453				Buffers[buffer][channel].base, Buffers[buffer][channel].stride);
454		}
455	}
456
457	if (fIsInput) {
458		List->return_record_channels += format->fNumChannels;
459		TRACE("return_record_channels:%#010x\n", List->return_record_channels);
460	} else {
461		List->return_playback_channels += format->fNumChannels;
462		TRACE("return_playback_channels:%#010x\n",
463												List->return_playback_channels);
464	}
465
466	return B_OK;
467}
468
469
470/*
471int32
472Stream::InterruptHandler(uint32 SignaledChannelsMask)
473{
474	uint32 ChannelMask = 1 << fHWChannel;
475	if ((SignaledChannelsMask & ChannelMask) == 0) {
476		return B_UNHANDLED_INTERRUPT;
477	}
478
479	uint32 CurrentSamplePositionFlag = fDevice->ReadPCI32(TrCurSPFBReg);
480
481	fRealTime = system_time();
482	fFramesCount += fBufferSize;
483	fBufferCycle = ((CurrentSamplePositionFlag & ChannelMask) == ChannelMask) ? 1 : 0;
484
485fCSP = CurrentSamplePositionFlag;
486
487	release_sem_etc(fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
488
489	return B_HANDLED_INTERRUPT;
490}*/
491
492
493bool
494Stream::ExchangeBuffer(multi_buffer_info* Info)
495{
496	if (fProcessedBuffers <= 0) {
497		// looks like somebody else has processed buffers but this stream
498		release_sem_etc(fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
499		return false;
500	}
501
502	Info->played_real_time = system_time();// TODO fRealTime;
503	Info->played_frames_count += fSamplesCount / kSamplesBufferCount;
504	Info->playback_buffer_cycle = fCurrentBuffer;
505
506	fCurrentBuffer++;
507	fCurrentBuffer %= kSamplesBufferCount;
508
509	atomic_add(&fProcessedBuffers, -1);
510
511	return true;
512}
513
514
515/*
516ASInterfaceDescriptor*
517Stream::ASInterface()
518{
519	return fAlternates[fActiveAlternate]->Interface();
520}
521
522
523_ASFormatDescriptor*
524Stream::ASFormat()
525{
526	return fAlternates[fActiveAlternate]->Format();
527}*/
528
529