jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

699 lines
19KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2005 Karsten Wiese, Rui Nuno Capela
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. //#include <jack/hardware.h>
  17. #include "hardware.h"
  18. #include "alsa_driver.h"
  19. #include "usx2y.h"
  20. //#include <jack/internal.h>
  21. //#include <jack/engine.h>
  22. #include <jack/messagebuffer.h>
  23. #include <sys/mman.h>
  24. #ifndef ARRAY_SIZE
  25. #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  26. #endif
  27. //#define DBGHWDEP
  28. #ifdef DBGHWDEP
  29. int dbg_offset;
  30. char dbg_buffer[8096];
  31. #endif
  32. static
  33. int usx2y_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask)
  34. {
  35. return -1;
  36. }
  37. static
  38. int usx2y_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode)
  39. {
  40. return -1;
  41. }
  42. static void
  43. usx2y_release (jack_hardware_t *hw)
  44. {
  45. usx2y_t *h = (usx2y_t *) hw->private;
  46. if (h == 0)
  47. return;
  48. if (h->hwdep_handle)
  49. snd_hwdep_close(h->hwdep_handle);
  50. free(h);
  51. }
  52. static int
  53. usx2y_driver_get_channel_addresses_playback (alsa_driver_t *driver,
  54. snd_pcm_uframes_t *playback_avail)
  55. {
  56. channel_t chn;
  57. int iso;
  58. snd_pcm_uframes_t playback_iso_avail;
  59. char *playback;
  60. usx2y_t *h = (usx2y_t *) driver->hw->private;
  61. if (0 > h->playback_iso_start) {
  62. int bytes = driver->playback_sample_bytes * 2 * driver->frames_per_cycle *
  63. driver->user_nperiods;
  64. iso = h->hwdep_pcm_shm->playback_iso_start;
  65. if (0 > iso)
  66. return 0; /* FIXME: return -1; */
  67. if (++iso >= ARRAY_SIZE(h->hwdep_pcm_shm->captured_iso))
  68. iso = 0;
  69. while((bytes -= h->hwdep_pcm_shm->captured_iso[iso].length) > 0)
  70. if (++iso >= ARRAY_SIZE(h->hwdep_pcm_shm->captured_iso))
  71. iso = 0;
  72. h->playback_iso_bytes_done = h->hwdep_pcm_shm->captured_iso[iso].length + bytes;
  73. #ifdef DBGHWDEP
  74. dbg_offset = sprintf(dbg_buffer, "first iso = %i %i@%p:%i\n",
  75. iso, h->hwdep_pcm_shm->captured_iso[iso].length,
  76. h->hwdep_pcm_shm->playback,
  77. h->hwdep_pcm_shm->captured_iso[iso].offset);
  78. #endif
  79. } else {
  80. iso = h->playback_iso_start;
  81. }
  82. #ifdef DBGHWDEP
  83. dbg_offset += sprintf(dbg_buffer + dbg_offset, "iso = %i(%i;%i); ", iso,
  84. h->hwdep_pcm_shm->captured_iso[iso].offset,
  85. h->hwdep_pcm_shm->captured_iso[iso].frame);
  86. #endif
  87. playback = h->hwdep_pcm_shm->playback +
  88. h->hwdep_pcm_shm->captured_iso[iso].offset +
  89. h->playback_iso_bytes_done;
  90. playback_iso_avail = (h->hwdep_pcm_shm->captured_iso[iso].length -
  91. h->playback_iso_bytes_done) /
  92. (driver->playback_sample_bytes * 2);
  93. if (*playback_avail >= playback_iso_avail) {
  94. *playback_avail = playback_iso_avail;
  95. if (++iso >= ARRAY_SIZE(h->hwdep_pcm_shm->captured_iso))
  96. iso = 0;
  97. h->playback_iso_bytes_done = 0;
  98. } else
  99. h->playback_iso_bytes_done =
  100. *playback_avail * (driver->playback_sample_bytes * 2);
  101. h->playback_iso_start = iso;
  102. for (chn = 0; chn < driver->playback_nchannels; chn++) {
  103. const snd_pcm_channel_area_t *a = &driver->playback_areas[chn];
  104. driver->playback_addr[chn] = playback + a->first / 8;
  105. }
  106. #ifdef DBGHWDEP
  107. if (dbg_offset < (sizeof(dbg_buffer) - 256))
  108. dbg_offset += sprintf(dbg_buffer + dbg_offset, "avail %li@%p\n", *playback_avail, driver->playback_addr[0]);
  109. else {
  110. printf(dbg_buffer);
  111. return -1;
  112. }
  113. #endif
  114. return 0;
  115. }
  116. static int
  117. usx2y_driver_get_channel_addresses_capture (alsa_driver_t *driver,
  118. snd_pcm_uframes_t *capture_avail)
  119. {
  120. channel_t chn;
  121. int iso;
  122. snd_pcm_uframes_t capture_iso_avail;
  123. int capture_offset;
  124. usx2y_t *h = (usx2y_t *) driver->hw->private;
  125. if (0 > h->capture_iso_start) {
  126. iso = h->hwdep_pcm_shm->capture_iso_start;
  127. if (0 > iso)
  128. return 0; /* FIXME: return -1; */
  129. h->capture_iso_bytes_done = 0;
  130. #ifdef DBGHWDEP
  131. dbg_offset = sprintf(dbg_buffer, "cfirst iso = %i %i@%p:%i\n",
  132. iso, h->hwdep_pcm_shm->captured_iso[iso].length,
  133. h->hwdep_pcm_shm->capture0x8,
  134. h->hwdep_pcm_shm->captured_iso[iso].offset);
  135. #endif
  136. } else {
  137. iso = h->capture_iso_start;
  138. }
  139. #ifdef DBGHWDEP
  140. dbg_offset += sprintf(dbg_buffer + dbg_offset, "ciso = %i(%i;%i); ", iso,
  141. h->hwdep_pcm_shm->captured_iso[iso].offset,
  142. h->hwdep_pcm_shm->captured_iso[iso].frame);
  143. #endif
  144. capture_offset =
  145. h->hwdep_pcm_shm->captured_iso[iso].offset +
  146. h->capture_iso_bytes_done;
  147. capture_iso_avail = (h->hwdep_pcm_shm->captured_iso[iso].length -
  148. h->capture_iso_bytes_done) /
  149. (driver->capture_sample_bytes * 2);
  150. if (*capture_avail >= capture_iso_avail) {
  151. *capture_avail = capture_iso_avail;
  152. if (++iso >= ARRAY_SIZE(h->hwdep_pcm_shm->captured_iso))
  153. iso = 0;
  154. h->capture_iso_bytes_done = 0;
  155. } else
  156. h->capture_iso_bytes_done =
  157. *capture_avail * (driver->capture_sample_bytes * 2);
  158. h->capture_iso_start = iso;
  159. for (chn = 0; chn < driver->capture_nchannels; chn++) {
  160. driver->capture_addr[chn] =
  161. (chn < 2 ? h->hwdep_pcm_shm->capture0x8 : h->hwdep_pcm_shm->capture0xA)
  162. + capture_offset +
  163. ((chn & 1) ? driver->capture_sample_bytes : 0);
  164. }
  165. #ifdef DBGHWDEP
  166. {
  167. int f = 0;
  168. unsigned *u = driver->capture_addr[0];
  169. static unsigned last;
  170. dbg_offset += sprintf(dbg_buffer + dbg_offset, "\nvon %6u bis %6u\n", last, u[0]);
  171. while (f < *capture_avail && dbg_offset < (sizeof(dbg_buffer) - 256)) {
  172. if (u[f] != last + 1)
  173. dbg_offset += sprintf(dbg_buffer + dbg_offset, "\nooops %6u %6u\n", last, u[f]);
  174. last = u[f++];
  175. }
  176. }
  177. if (dbg_offset < (sizeof(dbg_buffer) - 256))
  178. dbg_offset += sprintf(dbg_buffer + dbg_offset, "avail %li@%p\n", *capture_avail, driver->capture_addr[0]);
  179. else {
  180. printf(dbg_buffer);
  181. return -1;
  182. }
  183. #endif
  184. return 0;
  185. }
  186. static int
  187. usx2y_driver_start (alsa_driver_t *driver)
  188. {
  189. int err, i;
  190. snd_pcm_uframes_t poffset, pavail;
  191. usx2y_t *h = (usx2y_t *) driver->hw->private;
  192. for (i = 0; i < driver->capture_nchannels; i++)
  193. // US428 channels 3+4 are on a seperate 2 channel stream.
  194. // ALSA thinks its 1 stream with 4 channels.
  195. driver->capture_interleave_skip[i] = 2 * driver->capture_sample_bytes;
  196. driver->playback_interleave_skip[0] = 2 * driver->playback_sample_bytes;
  197. driver->playback_interleave_skip[1] = 2 * driver->playback_sample_bytes;
  198. driver->poll_last = 0;
  199. driver->poll_next = 0;
  200. if ((err = snd_pcm_prepare (driver->playback_handle)) < 0) {
  201. jack_error ("ALSA/USX2Y: prepare error for playback: %s", snd_strerror(err));
  202. return -1;
  203. }
  204. if (driver->midi && !driver->xrun_recovery)
  205. (driver->midi->start)(driver->midi);
  206. if (driver->playback_handle) {
  207. /* int i, j; */
  208. /* char buffer[2000]; */
  209. h->playback_iso_start =
  210. h->capture_iso_start = -1;
  211. snd_hwdep_poll_descriptors(h->hwdep_handle, &h->pfds, 1);
  212. h->hwdep_pcm_shm = (snd_usX2Y_hwdep_pcm_shm_t*)
  213. mmap(NULL, sizeof(snd_usX2Y_hwdep_pcm_shm_t),
  214. PROT_READ,
  215. MAP_SHARED, h->pfds.fd,
  216. 0);
  217. if (MAP_FAILED == h->hwdep_pcm_shm) {
  218. perror("ALSA/USX2Y: mmap");
  219. return -1;
  220. }
  221. if (mprotect(h->hwdep_pcm_shm->playback,
  222. sizeof(h->hwdep_pcm_shm->playback),
  223. PROT_READ|PROT_WRITE)) {
  224. perror("ALSA/USX2Y: mprotect");
  225. return -1;
  226. }
  227. memset(h->hwdep_pcm_shm->playback, 0, sizeof(h->hwdep_pcm_shm->playback));
  228. /* for (i = 0, j = 0; i < 2000;) { */
  229. /* j += sprintf(buffer + j, "%04hX ", */
  230. /* *(unsigned short*)(h->hwdep_pcm_shm->capture + i)); */
  231. /* if (((i += 2) % 32) == 0) { */
  232. /* jack_error(buffer); */
  233. /* j = 0; */
  234. /* } */
  235. /* } */
  236. }
  237. if (driver->hw_monitoring) {
  238. driver->hw->set_input_monitor_mask (driver->hw,
  239. driver->input_monitor_mask);
  240. }
  241. if (driver->playback_handle) {
  242. /* fill playback buffer with zeroes, and mark
  243. all fragments as having data.
  244. */
  245. pavail = snd_pcm_avail_update (driver->playback_handle);
  246. if (pavail != driver->frames_per_cycle * driver->playback_nperiods) {
  247. jack_error ("ALSA/USX2Y: full buffer not available at start");
  248. return -1;
  249. }
  250. if (snd_pcm_mmap_begin(
  251. driver->playback_handle,
  252. &driver->playback_areas,
  253. &poffset, &pavail) < 0) {
  254. return -1;
  255. }
  256. /* XXX this is cheating. ALSA offers no guarantee that
  257. we can access the entire buffer at any one time. It
  258. works on most hardware tested so far, however, buts
  259. its a liability in the long run. I think that
  260. alsa-lib may have a better function for doing this
  261. here, where the goal is to silence the entire
  262. buffer.
  263. */
  264. {
  265. /* snd_pcm_uframes_t frag, nframes = driver->buffer_frames; */
  266. /* while (nframes) { */
  267. /* frag = nframes; */
  268. /* if (usx2y_driver_get_channel_addresses_playback(driver, &frag) < 0) */
  269. /* return -1; */
  270. /* for (chn = 0; chn < driver->playback_nchannels; chn++) */
  271. /* alsa_driver_silence_on_channel (driver, chn, frag); */
  272. /* nframes -= frag; */
  273. /* } */
  274. }
  275. snd_pcm_mmap_commit (driver->playback_handle, poffset,
  276. driver->user_nperiods * driver->frames_per_cycle);
  277. if ((err = snd_pcm_start (driver->playback_handle)) < 0) {
  278. jack_error ("ALSA/USX2Y: could not start playback (%s)",
  279. snd_strerror (err));
  280. return -1;
  281. }
  282. }
  283. if (driver->hw_monitoring &&
  284. (driver->input_monitor_mask || driver->all_monitor_in)) {
  285. if (driver->all_monitor_in) {
  286. driver->hw->set_input_monitor_mask (driver->hw, ~0U);
  287. } else {
  288. driver->hw->set_input_monitor_mask (
  289. driver->hw, driver->input_monitor_mask);
  290. }
  291. }
  292. driver->playback_nfds = snd_pcm_poll_descriptors_count (driver->playback_handle);
  293. driver->capture_nfds = snd_pcm_poll_descriptors_count (driver->capture_handle);
  294. if (driver->pfd) {
  295. free (driver->pfd);
  296. }
  297. driver->pfd = (struct pollfd *)
  298. malloc (sizeof (struct pollfd) *
  299. (driver->playback_nfds + driver->capture_nfds + 2));
  300. return 0;
  301. }
  302. static int
  303. usx2y_driver_stop (alsa_driver_t *driver)
  304. {
  305. int err;
  306. JSList* node;
  307. int chn;
  308. usx2y_t *h = (usx2y_t *) driver->hw->private;
  309. /* silence all capture port buffers, because we might
  310. be entering offline mode.
  311. */
  312. for (chn = 0, node = driver->capture_ports; node;
  313. node = jack_slist_next (node), chn++) {
  314. jack_port_t* port;
  315. char* buf;
  316. jack_nframes_t nframes = driver->engine->control->buffer_size;
  317. port = (jack_port_t *) node->data;
  318. buf = jack_port_get_buffer (port, nframes);
  319. memset (buf, 0, sizeof (jack_default_audio_sample_t) * nframes);
  320. }
  321. if (driver->playback_handle) {
  322. if ((err = snd_pcm_drop (driver->playback_handle)) < 0) {
  323. jack_error ("ALSA/USX2Y: channel flush for playback "
  324. "failed (%s)", snd_strerror (err));
  325. return -1;
  326. }
  327. }
  328. if (driver->hw_monitoring) {
  329. driver->hw->set_input_monitor_mask (driver->hw, 0);
  330. }
  331. munmap(h->hwdep_pcm_shm, sizeof(snd_usX2Y_hwdep_pcm_shm_t));
  332. if (driver->midi && !driver->xrun_recovery)
  333. (driver->midi->stop)(driver->midi);
  334. return 0;
  335. }
  336. static int
  337. usx2y_driver_null_cycle (alsa_driver_t* driver, jack_nframes_t nframes)
  338. {
  339. jack_nframes_t nf;
  340. snd_pcm_uframes_t offset;
  341. snd_pcm_uframes_t contiguous, contiguous_;
  342. int chn;
  343. VERBOSE(driver->engine,
  344. "usx2y_driver_null_cycle (%p, %i)\n", driver, nframes);
  345. if (driver->capture_handle) {
  346. nf = nframes;
  347. offset = 0;
  348. while (nf) {
  349. contiguous = (nf > driver->frames_per_cycle) ?
  350. driver->frames_per_cycle : nf;
  351. if (snd_pcm_mmap_begin (
  352. driver->capture_handle,
  353. &driver->capture_areas,
  354. (snd_pcm_uframes_t *) &offset,
  355. (snd_pcm_uframes_t *) &contiguous)) {
  356. return -1;
  357. }
  358. contiguous_ = contiguous;
  359. while (contiguous_) {
  360. snd_pcm_uframes_t frag = contiguous_;
  361. if (usx2y_driver_get_channel_addresses_capture(driver, &frag) < 0)
  362. return -1;
  363. contiguous_ -= frag;
  364. }
  365. if (snd_pcm_mmap_commit (driver->capture_handle,
  366. offset, contiguous) < 0) {
  367. return -1;
  368. }
  369. nf -= contiguous;
  370. }
  371. }
  372. if (driver->playback_handle) {
  373. nf = nframes;
  374. offset = 0;
  375. while (nf) {
  376. contiguous = (nf > driver->frames_per_cycle) ?
  377. driver->frames_per_cycle : nf;
  378. if (snd_pcm_mmap_begin (
  379. driver->playback_handle,
  380. &driver->playback_areas,
  381. (snd_pcm_uframes_t *) &offset,
  382. (snd_pcm_uframes_t *) &contiguous)) {
  383. return -1;
  384. }
  385. {
  386. snd_pcm_uframes_t frag, nframes = contiguous;
  387. while (nframes) {
  388. frag = nframes;
  389. if (usx2y_driver_get_channel_addresses_playback(driver, &frag) < 0)
  390. return -1;
  391. for (chn = 0; chn < driver->playback_nchannels; chn++)
  392. alsa_driver_silence_on_channel (driver, chn, frag);
  393. nframes -= frag;
  394. }
  395. }
  396. if (snd_pcm_mmap_commit (driver->playback_handle,
  397. offset, contiguous) < 0) {
  398. return -1;
  399. }
  400. nf -= contiguous;
  401. }
  402. }
  403. return 0;
  404. }
  405. static int
  406. usx2y_driver_read (alsa_driver_t *driver, jack_nframes_t nframes)
  407. {
  408. snd_pcm_uframes_t contiguous;
  409. snd_pcm_sframes_t nread;
  410. snd_pcm_uframes_t offset;
  411. jack_default_audio_sample_t* buf[4];
  412. channel_t chn;
  413. JSList *node;
  414. jack_port_t* port;
  415. int err;
  416. snd_pcm_uframes_t nframes_ = nframes;
  417. if (!driver->capture_handle || driver->engine->freewheeling) {
  418. return 0;
  419. }
  420. if (driver->midi)
  421. (driver->midi->read)(driver->midi, nframes);
  422. nread = 0;
  423. if (snd_pcm_mmap_begin (driver->capture_handle,
  424. &driver->capture_areas,
  425. &offset, &nframes_) < 0) {
  426. jack_error ("ALSA/USX2Y: %s: mmap areas info error",
  427. driver->alsa_name_capture);
  428. return -1;
  429. }
  430. for (chn = 0, node = driver->capture_ports;
  431. node; node = jack_slist_next (node), chn++) {
  432. port = (jack_port_t *) node->data;
  433. if (!jack_port_connected (port)) {
  434. continue;
  435. }
  436. buf[chn] = jack_port_get_buffer (port, nframes_);
  437. }
  438. while (nframes) {
  439. contiguous = nframes;
  440. if (usx2y_driver_get_channel_addresses_capture (
  441. driver, &contiguous) < 0) {
  442. return -1;
  443. }
  444. for (chn = 0, node = driver->capture_ports;
  445. node; node = jack_slist_next (node), chn++) {
  446. port = (jack_port_t *) node->data;
  447. if (!jack_port_connected (port)) {
  448. /* no-copy optimization */
  449. continue;
  450. }
  451. alsa_driver_read_from_channel (driver, chn,
  452. buf[chn] + nread,
  453. contiguous);
  454. /* sample_move_dS_s24(buf[chn] + nread, */
  455. /* driver->capture_addr[chn], */
  456. /* contiguous, */
  457. /* driver->capture_interleave_skip); */
  458. }
  459. nread += contiguous;
  460. nframes -= contiguous;
  461. }
  462. if ((err = snd_pcm_mmap_commit (driver->capture_handle,
  463. offset, nframes_)) < 0) {
  464. jack_error ("ALSA/USX2Y: could not complete read of %"
  465. PRIu32 " frames: error = %d", nframes_, err);
  466. return -1;
  467. }
  468. return 0;
  469. }
  470. static int
  471. usx2y_driver_write (alsa_driver_t* driver, jack_nframes_t nframes)
  472. {
  473. channel_t chn;
  474. JSList *node;
  475. jack_default_audio_sample_t* buf[2];
  476. snd_pcm_sframes_t nwritten;
  477. snd_pcm_uframes_t contiguous;
  478. snd_pcm_uframes_t offset;
  479. jack_port_t *port;
  480. int err;
  481. snd_pcm_uframes_t nframes_ = nframes;
  482. driver->process_count++;
  483. if (!driver->playback_handle || driver->engine->freewheeling) {
  484. return 0;
  485. }
  486. if (driver->midi)
  487. (driver->midi->write)(driver->midi, nframes);
  488. nwritten = 0;
  489. /* check current input monitor request status */
  490. driver->input_monitor_mask = 0;
  491. for (chn = 0, node = driver->capture_ports; node;
  492. node = jack_slist_next (node), chn++) {
  493. if (((jack_port_t *) node->data)->shared->monitor_requests) {
  494. driver->input_monitor_mask |= (1<<chn);
  495. }
  496. }
  497. if (driver->hw_monitoring) {
  498. if ((driver->hw->input_monitor_mask
  499. != driver->input_monitor_mask)
  500. && !driver->all_monitor_in) {
  501. driver->hw->set_input_monitor_mask (
  502. driver->hw, driver->input_monitor_mask);
  503. }
  504. }
  505. if (snd_pcm_mmap_begin(driver->playback_handle,
  506. &driver->playback_areas,
  507. &offset, &nframes_) < 0) {
  508. jack_error ("ALSA/USX2Y: %s: mmap areas info error",
  509. driver->alsa_name_capture);
  510. return -1;
  511. }
  512. for (chn = 0, node = driver->playback_ports;
  513. node; node = jack_slist_next (node), chn++) {
  514. port = (jack_port_t *) node->data;
  515. buf[chn] = jack_port_get_buffer (port, nframes_);
  516. }
  517. while (nframes) {
  518. contiguous = nframes;
  519. if (usx2y_driver_get_channel_addresses_playback (
  520. driver, &contiguous) < 0) {
  521. return -1;
  522. }
  523. for (chn = 0, node = driver->playback_ports;
  524. node; node = jack_slist_next (node), chn++) {
  525. port = (jack_port_t *) node->data;
  526. alsa_driver_write_to_channel (driver, chn,
  527. buf[chn] + nwritten,
  528. contiguous);
  529. }
  530. nwritten += contiguous;
  531. nframes -= contiguous;
  532. }
  533. if ((err = snd_pcm_mmap_commit (driver->playback_handle,
  534. offset, nframes_)) < 0) {
  535. jack_error ("ALSA/USX2Y: could not complete playback of %"
  536. PRIu32 " frames: error = %d", nframes_, err);
  537. if (err != EPIPE && err != ESTRPIPE)
  538. return -1;
  539. }
  540. return 0;
  541. }
  542. static void
  543. usx2y_driver_setup (alsa_driver_t *driver)
  544. {
  545. driver->nt_start = (JackDriverNTStartFunction) usx2y_driver_start;
  546. driver->nt_stop = (JackDriverNTStopFunction) usx2y_driver_stop;
  547. driver->read = (JackDriverReadFunction) usx2y_driver_read;
  548. driver->write = (JackDriverReadFunction) usx2y_driver_write;
  549. driver->null_cycle =
  550. (JackDriverNullCycleFunction) usx2y_driver_null_cycle;
  551. }
  552. jack_hardware_t *
  553. jack_alsa_usx2y_hw_new (alsa_driver_t *driver)
  554. {
  555. jack_hardware_t *hw;
  556. usx2y_t *h;
  557. int hwdep_cardno;
  558. int hwdep_devno;
  559. char *hwdep_colon;
  560. char hwdep_name[9];
  561. snd_hwdep_t *hwdep_handle;
  562. hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t));
  563. hw->capabilities = 0;
  564. hw->input_monitor_mask = 0;
  565. hw->private = 0;
  566. hw->set_input_monitor_mask = usx2y_set_input_monitor_mask;
  567. hw->change_sample_clock = usx2y_change_sample_clock;
  568. hw->release = usx2y_release;
  569. /* Derive the special USB US-X2Y hwdep pcm device name from
  570. * the playback one, thus allowing the use of the "rawusb"
  571. * experimental stuff if, and only if, the "hw:n,2" device
  572. * name is specified. Otherwise, fallback to generic backend.
  573. */
  574. hwdep_handle = NULL;
  575. hwdep_cardno = hwdep_devno = 0;
  576. if ((hwdep_colon = strrchr(driver->alsa_name_playback, ':')) != NULL)
  577. sscanf(hwdep_colon, ":%d,%d", &hwdep_cardno, &hwdep_devno);
  578. if (hwdep_devno == 2) {
  579. snprintf(hwdep_name, sizeof(hwdep_name), "hw:%d,1", hwdep_cardno);
  580. if (snd_hwdep_open (&hwdep_handle, hwdep_name, O_RDWR) < 0) {
  581. jack_error ("ALSA/USX2Y: Cannot open hwdep device \"%s\"", hwdep_name);
  582. } else {
  583. /* Allocate specific USX2Y hwdep pcm struct. */
  584. h = (usx2y_t *) malloc (sizeof (usx2y_t));
  585. h->driver = driver;
  586. h->hwdep_handle = hwdep_handle;
  587. hw->private = h;
  588. /* Set our own operational function pointers. */
  589. usx2y_driver_setup(driver);
  590. printf("ALSA/USX2Y: EXPERIMENTAL hwdep pcm device %s"
  591. " (aka \"rawusb\")\n", driver->alsa_name_playback);
  592. }
  593. }
  594. return hw;
  595. }