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.

697 lines
18KB

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