Showing posts with label USB. Show all posts
Showing posts with label USB. Show all posts

Tuesday, August 28, 2012

External C-Media USB speakers on Ubuntu 11.10

I have a small-but-spiffy set of USB speakers, handy for travel. Here's how I got them to work.

First of all, there are a *lot* of moving pieces, and eliminating many potential sources of the problem (no sound emerges from the speakers) is critical to success.

For example, the speakers work on another system, so they aren't broken.

Other USB devices work in the port, so there's not a hardware defect.

Sound in general works on the laptop.

dmesg shows the speakers recognized appropriately when plugged in:
$ dmesg
[245788.608422] usb 1-1: ath9k_htc: USB layer initialized
[245789.124045] usb 3-1: new full speed USB device number 7 using ohci_hcd
[245789.261042] ADDRCONF(NETDEV_UP): wlan1: link is not ready
[245789.331223] input: C-Media USB Headphone Set   as /devices/pci0000:00/0000:00:13.1/usb3/3-1/3-1:1.3/input/input11
[245789.331380] generic-usb 0003:0D8C:000C.0003: input,hidraw0: USB HID v1.00 Device [C-Media USB Headphone Set  ] on usb-0000:00:13.1-1/input3

( If the hardware were not recognized, that would be a driver [kernel module] issue)

alsa shows the hardware properly recognized and configured. Alsa also creates a GUI mixer for the USB "card" when it's plugged in:
$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: SB [HDA ATI SB], device 0: ALC272X Analog [ALC272X Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: Set [C-Media USB Headphone Set], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Pulseaudio offers a good clue. It shows the USB card, but there is no sink for the USB card's output. Aha!
$ pacmd list-cards
Welcome to PulseAudio! Use "help" for usage information.
>>> 2 card(s) available.
    index: 0
 name: 
 driver: 
 owner module: 4
 properties:
               # It's the onboard audio
               # ...
 active profile: 
 sinks:
  alsa_output.pci-0000_00_14.2.analog-stereo/#0: Internal Audio Analog Stereo
 sources:
  alsa_output.pci-0000_00_14.2.analog-stereo.monitor/#0: Monitor of Internal Audio Analog Stereo
               # ...
    index: 7
 name: 
 driver: 
 owner module: 35
 properties:
  alsa.card = "1"
  alsa.card_name = "C-Media USB Headphone Set"
  alsa.long_card_name = "C-Media USB Headphone Set at usb-0000:00:13.1-1, full speed"
  alsa.driver_name = "snd_usb_audio"
  device.bus_path = "pci-0000:00:13.1-usb-0:1:1.0"
  sysfs.path = "/devices/pci0000:00/0000:00:13.1/usb3/3-1/3-1:1.0/sound/card1"
  udev.id = "usb-0d8c_C-Media_USB_Headphone_Set-00-Set"
  device.bus = "usb"
  device.vendor.id = "0d8c"
  device.vendor.name = "C-Media Electronics, Inc."
  device.product.id = "000c"
  device.product.name = "Audio Adapter"
  device.serial = "0d8c_C-Media_USB_Headphone_Set"
  device.form_factor = "headphone"
  device.string = "1"
  device.description = "Audio Adapter"
  module-udev-detect.discovered = "1"
  device.icon_name = "audio-headphones-usb"
 profiles:
  output:analog-stereo: Analog Stereo Output (priority 6000)
  output:analog-stereo+input:analog-mono: Analog Stereo Output + Analog Mono Input (priority 6001)
  input:analog-mono: Analog Mono Input (priority 1)
  off: Off (priority 0)
 active profile: 
 ports:
  analog-output-speaker: Analog Speakers (priority 10000, available: unknown)
  analog-input-microphone: Analog Microphone (priority 8700, available: unknown)
                # See? No output sink. 

There is probably a way out of this using output profiles, but I don't understand those yet. Instead, what appears to be needed is a udev rule that creates an output sink for the USB card, then redirects the default stream to use the USB card.

Upon plugging in the USB speakers, that udev rule should make the speakers the default sound device. Upon unplugging the speakers, the card and sink's disappearance will automatically force Pulseaudio to reroute the stream defaults to the onboard audio card and speakers.

Figure out the Pulseaudio index number of the USB card:
$ pacmd list-cards \
   | grep 'alsa.card_name = "C-Media USB Headphone Set"' --before-context=6 \
   | grep index \
   | cut -d' ' -f6

7

Figure out the alsa hardware number:
$ aplay -l | grep C-Media | cut -d' ' -f2 | cut -d: -f1

1

Add an alsa sink for the USB Card:
$ pacmd load-module module-alsa-sink device=hw:1,0

Figure out the Pulseaudio index number of the new alsa sink:
$ pacmd list-sinks | grep 'alsa.card_name = "C-Media USB Headphone Set"' --before-context=37 | grep index | cut -d' ' -f6

2

Change the default to the new sink
$ pacmd set-default-sink 2

Since the USB speakers are MUCH LOUDER than the onboard speakers, start them at a much lower level!
amixer -c 1 sset "Speaker" 5

So the final script should look something like:
#!/bin/sh
# This script makes the C-Media external USB speakers the
# default audio output. It should be run by udev.

# Figure out the Pulseaudio index number of the USB card
card_index=$( pacmd list-cards \
              | grep 'alsa.card_name = "C-Media USB Headphone Set"' \
              --before-context=6 | grep index | cut -d' ' -f6 )
echo "The USB card index is $card_index"

# Figure out the alsa hardware number
alsa_hardware=$( aplay -l | grep C-Media | cut -d' ' -f2 | cut -d: -f1 )
echo "The alsa hardware number is $alsa_hardware"

# Test if a USB sink already exists. If not, create one
if [ $( pacmd list-sinks | grep -q C-Media ) ]; then
   # Add an alsa sink for the USB Card
   pacmd load-module module-alsa-sink device=hw:${alsa_hardware},0
   echo "New alsa sink added"
fi

# Figure out the Pulseaudio index number of the alsa sink
alsa_sink_index=$( pacmd list-sinks \
                  | grep 'alsa.card_name = "C-Media USB Headphone Set"' \
                  --before-context=50 | grep index | cut -d' ' -f6 )
echo "Alsa sink index is $alsa_sink_index"

# If the current default sink is not the USB, change it
current_sink_index=$(pacmd list-sinks | grep '*' | cut -d' ' -f5)
if [ $current_sink_index -ne $alsa_sink_index ]; then
   # Change the default to the alsa sink
   pacmd set-default-sink ${alsa_sink_index}
   echo "Default sink changed from $current_sink_index to $alsa_sink_index"
else
   echo "Default sink not changed - it is already $current_sink_index"
fi

# Set the USB speaker levels very low to start
amixer -c ${card_index} sset "Speaker" 5
echo "Speaker volume changed"

exit 0
Save the script (newspeaker.sh), and remember to make it executable with chmod +x newspeaker.sh. Test it a bit. When the speakers are plugged in and the script run manually, the audio from the USB speakers is excellent. After unplugging, sound reverts to the onboard speakers. This is not a headphone jack - the audio must be stopped/started to use the changed

Sunday, May 27, 2012

Installing Debian 6 onto a VIA Epia 5000-L and IDE HDD

First boot with GUI
LXDE + Debian 6.0.5 on 10-year-old Epia 5000-L motherboard
I have a 10-year-old mini-ITX motherboard that I'm cobbling with a few parts into a useful system.

In this post, I discussed testing the old motherboard, and getting it to boot.

Since it arrived without any storage attached, in this post I discussed the hurdles getting it to boot Debian 6 from a USB drive. That wasn't easy, since the motherboard predated most forms of USB-boot, and the BIOS didn't support USB-HDD, the current standard for bootable USB.

Next, in this post, I discussed the adventure of using that USB boot to bootstrap a Debian install into an IDE-connected SD card. This didn't work out - one bootable IDE connector was defective, and a second worked...but wasn't bootable. I may return to this, since 3.5-inch HDDs are enormous - almost as big as the motherboard!

So I finally broke down and spent a few dollars on a 40GB HDD. This has the big advantage that the HDD can be partitioned for experimentation. Installing to the HDD is essentially the same process as installing to the SD card.




Lessons Learned

Hooked up:
Left: PS/2 Mouse, PS/2 Keyboard, VGA Monitor,
           USB Wireless-g dongle
Bottom: Power button
Right: Power to HDD, Power from wall, IDE to HDD
1) The -i486 architecture is important. This motherboard is too old to support cmov, cx8, and pae. All three of those are in the latest Ubuntu kernels. cmov and cx8 are part of the i686 instruction set, so specifying a i486 kernel gets rid of them. pae is a new default since Debian 6.0. So a Debian 6.0 kernel compiled for x486 will be useful on the motherboard...until I get better at compiling my own kernels.

2) Debootstrap does not include the wireless-tools package, so a bootstrapped system won't have wireless access. Adding wireless-tools is trivial if you remember to do it: During the chroot session when installing the kernel and grub and configuring the accounts and fstab and hostname, install wireless-tools and configure /etc/network/interfaces too.




For the first HDD experiment, I installed Debian 6 + LXDE onto a partition of the HDD.

Startup test: 45 Seconds from power-on to text-login prompt, 95 seconds to power-on to GDM login prompt.

Next tests: I want to try Debian Live for running the whole system in RAM. And I want to try modding the latest Ubuntu kernel to remove those three features and try Unity on it.

Sunday, January 8, 2012

Creating a bootable USB drive when the BIOS supports only USB-ZIP

Mini-ITX Epia 5000-L motherboard, ready to boot.
The red USB stick is the boot medium,
1GB USB stick with a complete Debian 6 install
masquerading as a 250MB USB-ZIP drive.

My used mini-ITX motherboard has a BIOS limitation that prevents it from booting from ordinary hybrid-iso images. The BIOS doesn't recognize USB-HDD (the popular type used today), but only older USB-FDD (USB floppy drive, limited to 1.4MB) or USB-ZIP (USB Zip Drive, limited to 250MB).

Who today has useful systems that fit in 250MB?

This is a demonstration of how to use a chainloader to get around the 250MB restriction. Here is how to build a working full install of Debian 6 on a bootable USB Stick. It's a full install (not a live-install that uses a ramdisk), so all the slow read/writes to the USB stick will make the system very slow and wear out the USB stick prematurely. Again, this is just a demo of how to use a chainloader to get around that 250MB restriction.

1) Create the Linux system

This is the long and complicated part. Use debootstrap to create a complete system somewhere else. I explained how I did it in this post for an SD card, and it's almost exactly the same.

Creating the complete system in, say, /var/usb-env should include creating /boot/initrd.img.version# and vmlinuz.version# , but not grub. We will use initrd.img and vmlinuz in Step #3, and this demo uses the simpler syslinux instead of grub.

2) Prepare the USB Stick

To be understood by the old BIOS, the USB stick needs an MBR up front, followed by a FAT boot partition of less than 250MB and labeled as the 4th partition (though it's really the first partition). After that, we can do whatever we like.

The best tool for creating a USB-ZIP bootable partition is 'mkdiskimage', part of the syslinux package. Everything below should be done as root to the unmounted USB-stick:
MAKE SURE you are using the right /dev/DEVICE
    /dev/sdb was mine, but probably won't be yours!

# mkdiskimage -Mz4 -i usb-zip /dev/sdb 15 64 32
    -M and 15: Create a 15 MB partition (I only needed 12 MB)
    -z4: Create a zip-disk geometry on partition 4 (normal for zip disks)
    -i usb-zip: Name of the partition. Use any name you wish
    Of course, your /dev/DEVICENODE may vary. BE SURE you are using the right node!
    15 64 32: 15 MB (see -M), 64 heads, 32 sectors (62 and 32 are required for zip)

After the USB-ZIP partition is made, you can do the rest of the partitions in your favorite editor. I used Gparted to create a 700MB Linux partition and the remaining space on the device as a swap partition.

3) Install files onto the boot partition

The install files consist of the bootloader, and the Linux /boot/initrd.img.version# and vmlinuz.version# files. The bootloader simply tells the system to load the linux kernel (vmlinuz), then to load the temporary system startup files (initrd.img) that the kernel can understand. One of the appended command options tells initrd where to find the final system root mountpoint on the other partition.

There are many bootloaders that can be used here, including grub. For simplicity, I'm using syslinux instead of grub. I don't need all of grub's configuration options - I just want the bootloader to immediately start loading the kernel and initrd.

For syslinux, we only need four files on the boot partition: The syslinux binary, syslinux.cfg, vmlinuz, and initrd.img. We also need to know the UUID of the other partitions for the syslinux.cfg file.
Once again, MAKE SURE you are using the right /dev/DEVICE
    /dev/sdb was mine, but probably won't be yours!

    Check the USB stick partitions before mounting
# fsck -f /dev/sdb1  # Blank linux, -f forces a check
# fsck -f /dev/sdb4  # Blank boot

    Get the UUIDs of the various partitions
# blikd   # Get the UUIDs of the newly created partitions

    Install Syslinux 
# syslinux --install /dev/sdb4

    Mount the boot partition
# mount -t vfat /dev/sdb4 /mnt

    Copy vmlinuz and initrd.img from the prepared system.
    Rename the files to comply with MSDOS 8.3 format
# cp /var/usb-env/vmlinuz.version /mnt/vmlinuz
# cp /var/usb-env/initrd.img.version /mnt/initrd.img

    Create the syslinux.cfg file
# nano /mnt/syslinux.cfg    # Use any editor you wish

##### Begin File
Default USB-Stick

display syslinux.msg
F1      syslinux.f1

prompt 40
timeout 30

Label USB-Stick
  kernel vmlinuz
  append initrd=initrd.img root=UUID=>UUID of the root partition<
##### End file

    Unount the boot partition
# umount /mnt

4) Copy the linux system onto the USB Stick

Once again, MAKE SURE you are using the right /dev/DEVICE
    /dev/sdb was mine, but probably won't be yours!

    Mount the Linux partition
# mount /dev/sdb1 /mnt

    Copy the system files
# cp -r /var/usb-env/{bin,etc,home,lib,media,mnt,opt,root,sbin,selinux,srv,tmp,usr,var} /mnt/

    Create the system mountpoints
# mkdir /mnt/{boot,dev,proc,sys}

    Edit /etc/fstab to add the correct UUIDs for the root, boot, and swap partitions
    and remove the cruft from the creating-system disks.
If you need to discover a UUID, use the 'blkid' command.
# nano /mnt/etc/fstab     # Use any editor you wish, of course

#####Begin File
# <file system> <mount point> <type> <options> <dump>  <pass>
UUID=<UUID of the main system> / ext3 defaults,errors=remount-ro,noatime 0 1
UUID=<UUID of the boot partition> /boot vfat defaults,errors=remount-ro,noatime 0 2 
UUID=<UUID of the swap partition> none  swap sw 0 0 
#####End File

    Unmount the linux partition, check the USB stick for damage once more
# umount /mnt
# fsck -f /dev/sdb4
# fsck -f /dev/sdb1

Successful boot to Debian 6 login prompt!
5) You're Done

Unplug the USB stick, walk over to the system you want to boot, plug in the USB stick, and....well, boot.

Saturday, March 8, 2008

Mounting a USB stick drive on an OLPC Laptop

Success! How do you mount a USB stick on an OLPC laptop and get a window of the contents?

Tip #1: Try several of the USB ports. I was successful in the lower right side port.

Tip #2: Once inserted, the USB stick will automount under /media/UsbStickName. Just do an ls /media/ to see your stick there.

Tip #3: For the GUI, look in the Journal. The stick shows as an icon on the bottom. Click it, and the window of contents opens!

Tip #4: To unmount and eject the drive, use the Journal's USB Drive icon. Trying to use the umount command in Terminal fails, claiming the drive is busy.