GNU/Linux y Nintendo DS

— [ edit | raw ] migrated from node/622
¿Qué? ¿Cómo? ¿Que tienes una Nintendo DS por casa? ¡¡Estás de suerte!!. Con unos minutos, la lectura de esta recetilla, un espíritu jóven y la ayuda del Software Libre tienes en tus manos un maquinón al que le podrás sacar todo el jugo. Veamos cómo....

Introducción

Pues lo dicho. La Nintendo DS (NDS a partir de ahora), es un "cacharrito" que tiene dentro un ARM7 y un ARM9 trabajando en paralelo. También dispone de WIFI, pantalla táctil y un buen audio (entre otras muchas cosas, aún no he podido profundizar mucho en la arquitectura hardware de la máquina). Si queremos introducirnos en el mundo del homebrew para ésta consola (o scene, con lo que encontrareis mas cosas googleando -thanks int0-) , gracias al Software Libre lo tenemos francamente fácil, ya que tenemos en nuestras manos herramientas tales como emuladores, librerías cruzadas, etc..... es decir, una toolchain completa. Aquí iré explicando paso a paso cómo la he instalado en mi máquina, ya que todo ésto ha sido la "recopilación" de varias búsquedas por la red y de varias consultas en algún que otro foro (gracias chicos, por la paciencia con los novatos ;))

Primeros pasos: Descargando fuentes

Todos los fuentes de las librerías que necesitamos se encuentran en sourceforge. Aquí se pueden encontrar tanto las librerías ya compiladas como los fuentes. Yo en mi caso he preferido bajarme los fuentes y compilarmelos (como está mandao 8)). Ésto es todo lo que hace falta para poder empezar a trabajar:
  • build scripts
  • libfat
  • dswifi
  • y por supuesto nds-examples
Nos bajaremos las útlimas versiones de dichos paquetes para evitar problemas de compatibilidades. En arco he dejado los paquetes que he utilizado yo. En el momento en el que escribo este documento (marzo de 2007), la versión de build scripts es la 20060724. Ésta descarga unos paquetes un poco "anticuados", así que he modificado uno de los scripts que hay dentro del paquete y lo he dejado fuera. Éste script debereis descargarlo para poder compilar la toolchain correctamente.

Instalación

Bueno, pues suponiendo que tenemos el directorio nds que hay en ARCo dentro de nuestra máquina, procederemos a compilar la toolchain. Entramos en el directorio scripts y descomprimimos el paquete que contiene los scritps de instalación. Una vez que hayamos hecho eso, sobreescribimos el script build-devkit.sh con el script del mismo nombre que hay en el raiz. Es decir:
javieralso@Gezel:~/nds/scripts$ bunzip2 -c buildscripts-20060724.tar.bz2 | tar xf -
javieralso@Gezel:~/nds/scripts$ cp -f ../build-devkit.sh ./
A continuación ejecutamos el script. Cuando hagamos ésto, nos preguntará para qué arquitectura queremos el kit. En nuestro caso la queremos para arm (ds, gp2 y gba), así que pulsamos la opción 1. Después le decimos que queremos que descargue los paquetes y finalmente dónde queremos que nos compile la toolchain:
javieralso@Gezel:~/nds/scripts$ ./build-devkit.sh
This script will build and install your devkit. Please select the one you require
1: build devkitARM (gba gp32 ds)
2: build devkitPPC (gamecube)
3: build devkitPSP (PSP)
1
The installation requires binutils-2.17, gcc4.1.1 and newlib-1.14.0.  Please select an option:
1: I have already downloaded the source packages
2: Download the packages for me (requires wget)
2
Please enter the directory where you would like 'devkitARM' to be installed:
for mingw/msys you must use <drive>:/<install path> or you will have include path problems
this is the top level directory for devkitpro, i.e. e:/devkitPro
/usr/local/stow/dkp
Yo en mi caso le he dicho que quiero que me instale la toolchain en el directorio /usr/local/stow/dkp, aunque ésto no es nada crítico. En éste momento, comenzará la descarga, descompresión, compilación e instalación de los paquetes. Deberemos ser pacientes, ya que puede tardar su tiempo. Cuando termina de descargar los paquetes nos pide confirmación para comenzar la instalación. Confirmamos y ya ta :D Después de finalizar ésta parte, deberemos exportar los PATH's para que cuando compilemos los makefiles sepan cuales son las rutas. Para ello editamos nuestro archivo ~/.bashrc y añadimos lo siguiente:
export DEVKITPRO=/usr/local/stow/dkp
export DEVKITARM=/usr/local/stow/dkp/devkitARM
export LIBNDS=/usr/local/stow/dkp/libnds
export LIBNDS_INCLUDE=/usr/local/stow/dkp/libnds/include
export LIBNDS_LIB=/usr/local/stow/dkp/libnds/lib
Vosotros debereís introducir vuestras rutas. Cuando hayais hecho ésto tendreis lo básico funcionando y ya podreís hacer programas bastante interesantes...

Librerías extra

Dentro del subdirectorio libs tenemos los fuentes de las librerías para la wifi (dswifi) y los fuentes para las librerías de sistema de archivos FAT (libfat). Éstas librerías no se instalan de forma automática, pero es muy fácil hacerlo manualmente.

Instalación de dswifi

descomprimimos el archivo con las fuentes (en una shell nueva, para que los PATHs se hayan cargado) y ejecutamos make y después make install:
javieralso@Gezel:~/nds/libs$ bunzip2 -c dswifi-src-0.3a.tar.bz2 | tar xf -
javieralso@Gezel:~/nds/libs$ make
javieralso@Gezel:~/nds/libs$ make install
Con ésto, la librería habrá quedado instalada en nuestro sistema :D

Instalación de libfat

PENDIENTE

A probarlo todo :P

Bueno, pues ahora ya estamos listos para compilar algunos ejemplos y probarlos en nuestra NDS. Dentro del directorio ejemplos tenemos un paquetito con montones de ejemplos de manejo de la wifi, la pantalla táctil, gráficos en 2D y 3D y un largo etcétera. Para probarlos es tan fácil como descomprimir el paquete y ejecutar make desde el raiz. Si todo funciona bien (que debería ser así) se generará un directorio bin en el que estarán todos los archivos *.nds listos para ser cargados en nuestra NDS

Y para la próxima....

Bueno, pues por mucha consola que tengamos, no está de mas tener un emulador para hacer pruebas rápidas sin tener que cargarlas en la máquina (que puede ser un poco engorroso). Próximamente explicaré como instalar dsmume, un emulador bastante majo que corre también en GNU/Linux y que aunque tiene algunas limitaciones, nos permitirá, por ejemplo, probar varios de los ejemplos que hemos compilado anteriormente.

Referencias

Manejo básico de señales en GNU/Linux

— [ edit | raw ] migrated from node/621
Un manual muy básico de cómo manejar señales en GNU/Linux

Introducción

GNU/Linux soporta las llamadas Señales fiables POSIX y las Señales en Tiempo Real POSIX. No voy a listar todas éstas señales, ya que se encuentran en signal.h y se pueden consultar en cualquier manual de GNU/Linux Para explicar el proceso de escribir un manejador de señales (en C), usaré un ejemplo muy sencillo y lo iré explicando después.

El código de ejemplo

Bueno, éste es el código que utilizaré como ejemplo. Guardadlo en un archivo con el nombre que querais y lo compilais con gcc (como toda la vida :D)
#include <stdio.h>
#include <signal.h>
#include <string.h>

void timerHandler();

int main () {
  struct sigaction sigTimerAction;

  memset (&sigTimerAction, 0, sizeof(sigTimerAction));

  sigTimerAction.sa_handler = timerHandler;
  sigTimerAction.sa_restorer = NULL;

  sigaction (SIGALRM, &sigTimerAction, NULL);

  alarm((unsigned int)1);

  while(1);
}

void timerHandler() {
  static int c;

  printf ("Contador %i\n", c++);
  alarm ((unsigned int)1);
}

Funcionamiento

Bueno, el código está formado por dos funciones, una es el main de toda la vida. La otra, timerHandler es el manejador de señales, que se ejecutara, en este caso, cada vez que se lance una señal SIGALRM. La función del manejador no tiene mucho misterio. Tan solo se trata de una línea que imprime el valor de un contador y una función que restaura el temporizador para que se lance una señal un segundo después de ejecutarse (Bueno, no es un segundo exacto, recordad que estamos en un entorno multiprogramado ;)). La función main empieza con una instancia de una estructura tipo sigaction. Es en ésta estructura donde se guarda la información de qué manejador se asocia a qué señal. La implementación de sigaction es la siguiente:
struct sigaction {
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
}
y la utilidad de los campos de dicha estructura es la que sigue a continuación:
  • sa_restorer: Está obsoleto y no debería utilizarse. POSIX no especifica ningún elemento sa_restorer.
  • sa_handler: Especifica la acción asociada a la señal signum. Ésta acción puede ser:
    • SIG_DFL para la acción por defecto,
    • SIG_IGN para ignorar la señal o
    • un puntero a una función que actue como manejador de dicha señal.
  • sa_mask: Proporciona una máscara de señales que deben ser bloqueadas durante la ejecución del manejador de señal. Además, la señal que activó el manejador actual también será bloqueada a menos que se utilicen los flags SA_NODEFER o SA_NOMASK.
  • sa_flags: Especifica un conjunto de flags que pueden variar el comportamiento del manejador de señal.
  • signum: Especifica la señal a capturar y puede ser cualquier señal válida excepto SIGKILL y SIGSTOP.
Bueno, podemos ver que después de limpiar (o iniciliazar para los mas puristas) la estructura, asignamos el manejador que queremos que sea ejecutado en el campo sa_handler. sa_restorer es mejor inicializarlo a NULL para evitar problemas. A continuación, se llama la función sigaction (¿de qué me sonará el nombre? ;)). El prototipo de ésta función, es el que sigue:
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
Los argumentos son estos:
  • int signum: Se utiliza para especificar la señal que desea capturarse.
  • const struct sigaction *act: Especifica la estructura sigaction en la que se encuentra la información sobre el manejador a asociar a la señal capturada.
  • struct sigaction *oldact: Una estructura en la que se almacenará la información del antiguo manejador instalado para esa señal. Se puede dejar a NULL si se desea.
La función sigaction retorna 0 si todo ha ido bien y -1 si ha habido algún error. En nuestro caso, utilizamos ésta función para asociar timerHandler con la señal SIGALRM. Una vez hecho esto, ya solo queda llamar a la función alarm para que se lance una señal SIGALRM en un segundo y generar un bucle infinito para que el programa no finalice nunca ;).

Referencias

Mantener un paquete Debian con svn-buildpackage

— [ edit | raw ] migrated from node/620

Esta receta explica cómo usar la herramienta svn-buildpackage para mantener un paquete Debian existente.

Empezar con ZeroC Ice en Debian

— [ edit | raw ] migrated from node/619
En esta receta se describe cómo instalar el middleware ZeroC ICE en Debian SID y cómo ejecutar un ejemplo básico en Python.

Introducción

ZeroC ICE es un middleware orientado a objetos, es decir, ICE proporciona herramientas, APIs, y soporte de bibliotecas para construir aplicaciones cliente-servidor orientadas a objetos. La filosofía de ZeroC ICE es la construcción de una plataforma tan potente como CORBA, pero sin cometer todos los fallos de ésta y evitando una complejidad innecesaria. ICE es software libre y está liberado bajo la licencia GNU/GPL.

Instalación

Si somos usuarios de Debian y/o derivados, la instalación es muy sencilla:
# apt-get update
# apt-get install zeroc-ice33

¡Hola, mundo!

El lenguaje de especificación de interfaces de ICE es Slice, y se utiliza para definir las interfaces, las operaciones, y los tipos de datos intercambiados entre el cliente y el servidor, entre otras cosas. El clásico ejemplo de ¡Hola, mundo! en Slice sería muy sencillo:
module Demo {
   interface HolaMundo {
     void saludar ();
   };
};

¡Hola, mundo! en Python

Cliente:
import sys, traceback, Ice
Ice.loadSlice('holaMundo.ice', ['-I' '/usr/share/slice'])
import Demo

class Client (Ice.Application):
    def run (self, argv):
        basePrx = self.communicator().stringToProxy('HolaMundo:default -p 10000')
        holaMundoPrx = Demo.HolaMundoPrx.checkedCast(basePrx)
        holaMundoPrx.saludar()
        return 0

Client().main(sys.argv)
El cliente simplemente crea un proxy a un objeto que implementa la interfaz HolaMundo y, posteriormente, invoca a la operación saludar. Servidor:
import sys, traceback, Ice
Ice.loadSlice('../slice/HolaMundo.ice', ['-I' '/usr/share/slice'])
import Demo

class HolaMundoI (Demo.HolaMundo):
    def saludar (self, current = None):
        print '¡Hola Mundo!'

class Server (Ice.Application):
    def run (self, argv):
        self.shutdownOnInterrupt()
        adapter = self.communicator().createObjectAdapterWithEndpoints(
            'HolaMundoAdapter', 'default -p 10000')
        adapter.add(HolaMundoI(), self.communicator().stringToIdentity('HolaMundo'))
        adapter.activate()
        self.communicator().waitForShutdown()
        return 0

Server().main(sys.argv)
El servidor crea un objeto de tipo HolaMundo y lo registra en un adaptador de objetos, encargado de manejar las operaciones remotas (o locales) sobre sus objetos asociados.

Ejecución

Servidor:
$ python Server.py
Cliente:
$ python Client.py

Referencias

ZeroC

Port-knocking: "llama antes de entrar"

Cómo instalar y configurar knockd, un demonio de port-knocking

Prueba de logo

— [ edit | raw ] migrated from node/615
¿Qué tal? ¿Lo ponemos? Se admiten sugerencias

Nueva camisetilla...

— [ edit | raw ] migrated from node/616

Pues nada, se aceptan todo típo de críticas. Sugenencias no, porque si quereís algo, os bajáis el fuente y os ponéis a currar :)

Advertencia sanitaria

Un nuevo diseño que advierte de los peligros de usar software privativo.



Todas las camisetas en: Diseña la moda

Un saludo!"

Empaquetar un script Python para Debian (y mantenerlo)

— [ edit | raw ] migrated from node/325

Esta receta explica de forma muy resumida los pasos más importantes para crear y mantener un paquetillo Debian, y cumpliendo la política de Debian.

Dot Net Club (don't set club)

— [ edit | raw ] migrated from node/613
Antes de empezar, algo que escuché cuando venía para la escuela:

generate_m3u

— [ edit | raw ] migrated from node/611

Esto es tan chorra que casi me da pena ponerlo, pero bueno, igual a alguien le sirve. Pues eso, se trata de un “script” (una línea de shell) para general un fichero .m3u a partir de los ficheros .mp3 que haya en un directorio, o sea: