Ни о чём →
Звуковая карта в качестве консольного устройства
Poul-Henning Kamp в списке рассылки freebsd-arch продемонстрировал пример кода, позволяющего осуществлять консольный ввод-вывод через звуковую карту. Оригинал его письма здесь, а я предлагаю свой, по возможности максимально близкий к оригиналу, перевод. Некоторые слова я перевести не смог, поэтому оставляю в оригинале и в скобках даю свои предположения.
Вчера, когда я страдал фигней, занимаясь со своим новым лэптопом и функциями приостановки/возобновления ACPI, я снова поймал себя на том, что проклинаю того чокнутого, который убрал (с лэптопов — прим. перев.) наши последовательные порты.
Я подумал немного и меня внезапно озарило: все современные устройства имеют встроенную поддержку звукового оборудования AC97, предоставляющего довольно хорошую пропускную способность.
Этим утром я начал простой эксперимент. Результат ясно дает понять, что идея рабочая, хотя и работает from userland (может быть, в пространстве пользователя? определения Google дают именно такой ответ — прим. перев.).
Я использовал следующий формат для передачи: посылка кратковременного отрицательного перепада для начала символа, а затем N дискрет, затем положительный перепад. N — ASCII-значение символа + маленькая константа.
Я прилагаю код, подтверждающий концепцию(proof-of-concept в оригинале — прим. перев.), который использует два стереоканала на дифференциальной паре (не уверен, что это хорошая идея).
В первой попытке, я был способен передавать около 320 символов в секунду с 1% ошибок.
Что осталось сделать:
* оптимизировать схему передачи.
Это может быть сделано с помощью двух компьютеров, кабеля jack-в-jack и немного кода на C.
Различие в частоте дискрет на у двух компьютеров приводит к ошибке занижения или завышения на единицу. Я не знаю, может ли детектор пиков с интерполяцией решить эту проблему, либо мы будем вынуждены использовать дискретизацию с запасом по частоте (oversampling — прим. перев.) в приемнике.
Два импульса могут иметь различные полярности, т.е. мы можем передавать два бита, что может повысить скорость передачи на множитель четырех (factor of four скорее всего означает именно это — прим. перев.), если найдем способ должным образом выполнить синхронизацию.
Два стереоканала могут быть использованы независимо, вдвое увеличивая скорость.
* написать дравер консоли уровня ядра, работающий со звуковым оборудованием без использования прерываний.
Я не знаю, как выглядит интерфейс к звуковой карте, но я подозреваю, что довольно просто.
Даже если соединение будет однонаправленное, хакеры ядра, вроде меня, будут почитать любого, который закончит эту работу.
Налетай!
Poul-Henning
—
—
—
Это произведение доступно по лицензии Creative Commons Attribution-ShareAlike (Атрибуция — С сохранением условий) 3.0 Непортированная.
Вчера, когда я страдал фигней, занимаясь со своим новым лэптопом и функциями приостановки/возобновления ACPI, я снова поймал себя на том, что проклинаю того чокнутого, который убрал (с лэптопов — прим. перев.) наши последовательные порты.
Я подумал немного и меня внезапно озарило: все современные устройства имеют встроенную поддержку звукового оборудования AC97, предоставляющего довольно хорошую пропускную способность.
Этим утром я начал простой эксперимент. Результат ясно дает понять, что идея рабочая, хотя и работает from userland (может быть, в пространстве пользователя? определения Google дают именно такой ответ — прим. перев.).
Я использовал следующий формат для передачи: посылка кратковременного отрицательного перепада для начала символа, а затем N дискрет, затем положительный перепад. N — ASCII-значение символа + маленькая константа.
Я прилагаю код, подтверждающий концепцию(proof-of-concept в оригинале — прим. перев.), который использует два стереоканала на дифференциальной паре (не уверен, что это хорошая идея).
В первой попытке, я был способен передавать около 320 символов в секунду с 1% ошибок.
Что осталось сделать:
* оптимизировать схему передачи.
Это может быть сделано с помощью двух компьютеров, кабеля jack-в-jack и немного кода на C.
Различие в частоте дискрет на у двух компьютеров приводит к ошибке занижения или завышения на единицу. Я не знаю, может ли детектор пиков с интерполяцией решить эту проблему, либо мы будем вынуждены использовать дискретизацию с запасом по частоте (oversampling — прим. перев.) в приемнике.
Два импульса могут иметь различные полярности, т.е. мы можем передавать два бита, что может повысить скорость передачи на множитель четырех (factor of four скорее всего означает именно это — прим. перев.), если найдем способ должным образом выполнить синхронизацию.
Два стереоканала могут быть использованы независимо, вдвое увеличивая скорость.
* написать дравер консоли уровня ядра, работающий со звуковым оборудованием без использования прерываний.
Я не знаю, как выглядит интерфейс к звуковой карте, но я подозреваю, что довольно просто.
Даже если соединение будет однонаправленное, хакеры ядра, вроде меня, будут почитать любого, который закончит эту работу.
Налетай!
Poul-Henning
—
/* proof of concept transmission code */
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/soundcard.h>
#define OFF 5
static short int buf[2*128 + 2 * OFF];
int
main(int argc __unused, char **argv __unused)
{
int fd_dsp;
int i, j, k, c;
fd_dsp = open("/dev/dsp0.1", O_RDWR);
if (fd_dsp < 0)
err(1, "open /dev/dsp");
i = ioctl(fd_dsp, SNDCTL_DSP_RESET, &j);
assert(i == 0);
j = 2;
i = ioctl(fd_dsp, SNDCTL_DSP_CHANNELS, &j);
assert(i == 0);
j = 44100;
i = ioctl(fd_dsp, SNDCTL_DSP_SPEED, &j);
assert(i == 0);
j = 16;
i = ioctl(fd_dsp, SNDCTL_DSP_SETFMT, &j);
assert(i == 0);
while (1) {
c = getchar();
if (c == EOF)
break;
buf[OFF] = 32000;
buf[OFF + 1] = -32000;
buf[OFF + 2 * c] = -32000;
buf[OFF + 2 * c + 1] = 32000;
i = write(fd_dsp, buf, sizeof buf);
assert(i == sizeof buf);
buf[OFF + 2 * c] = 0;
buf[OFF + 1 + 2 * c] = 0;
}
exit (0);
}
—
/* proof of concept reception code */
#include <assert.h>
#include <stdio.h>
static int
sample(FILE *f, const char *p)
{
short l, r;
int i, s;
i = fread(&l, sizeof l, 1, stdin);
assert(i == 1);
i = fread(&r, sizeof l, 1, stdin);
assert(i == 1);
s = l;
s -= r;
if (0 && p != NULL)
printf("%6d %s\n", s, p);
return (s);
}
static void
find_neg_peak(FILE *f)
{
int s, sl;
while (1) {
s = sample(stdin, "v");
if (s < -10000)
break;
}
sl = s;
while (1) {
s = sample(stdin, "N");
if (s > sl)
return;
sl = s;
}
}
static int
find_pos_peak(FILE *f)
{
int s, sl, k;
k = 0;
while (1) {
k++;
s = sample(stdin, "^");
if (s > 10000)
break;
}
sl = s;
while (1) {
k++;
s = sample(stdin, "P");
if (s < sl)
return (k);
sl = s;
}
}
int
main(int argc __unused, char **argv)
{
short l, r;
int i, k, p, s, sl;
k = 0;
p = 0;
while (1) {
find_neg_peak(stdin);
k = find_pos_peak(stdin);
if (k == 10)
printf("\\n\n");
else if (k >= ' ' && k <= '~')
printf("%c", k);
else
printf("\\x%02x", k);
}
exit (0);
}
—
Это произведение доступно по лицензии Creative Commons Attribution-ShareAlike (Атрибуция — С сохранением условий) 3.0 Непортированная.
01.12.2006 21:20+0300