Controlador de dispositivos USB de Android

Estoy tratando de hacer que Ethernet a través de USB funcione para mi Nexus S. Estoy ejecutando Ice Cream Sandwich v4.0.3 y he reconstruido el kernel con la compatibilidad con USB Gadget activada. Cuando conecto el teléfono a mi caja de Linux y ejecuto ifconfig -a, usb0 aparece tanto en el teléfono como en la caja de Linux. Ejecuto ifconfig para configurar ambos lados y todo parece correcto, pero no puedo hacer ping desde ninguno de los lados:

PING 192.168.22.2 (192.168.22.2) 56(84) bytes of data.
From 192.168.22.1 icmp_seq=1 Destination Host Unreachable
From 192.168.22.1 icmp_seq=2 Destination Host Unreachable

También tengo un N900 con Maemo Linux que permite Ethernet a través de USB. Comparé la salida de ethtool, ifconfig, route y arp entre el N900 y el Nexus S y todos son muy similares excepto la salida arp. Muestra (incompleto) para la dirección HW para la conexión de Android:

Address                  HWtype  HWaddress           Flags Mask            Iface
10.1.3.1                 ether   00:1B:17:05:30:13   C                     eth0
192.168.22.2                     (incomplete)                              usb0

La única otra pista que tengo es que ifconfig se muestra en el lado de Linux:

usb0      Link encap:Ethernet  HWaddr 66:E4:64:10:D1:A9  
      inet addr:192.168.22.1  Bcast:192.168.22.255  Mask:255.255.255.0
      inet6 addr: fe80::64e4:64ff:fe10:d1a9/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:0 errors:0 dropped:0 overruns:0 frame:0
      TX packets:42 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000 
      RX bytes:0 (0.0 b)  TX bytes:9039 (8.8 KiB)

y en el lado de Android:

usb0      Link encap:Ethernet  HWaddr 7A:78:28:52:9C:A0
      inet addr:192.168.22.2 Bcast:192.168.22.255 Mask:255.255.255.0
      inet6 addr: fe80::7878:28ff:fe52:9ca0/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:202 errors:0 dropped:202 overruns:0 frame:0
      TX packets:36 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000
      RX bytes:47294 (46.1 KiB)  TX bytes:1728 (1.6 KiB)

Observe los paquetes caídos en el lado de Android.

Parece que ya casi estoy... ¿alguna sugerencia?

EDITAR:

Reconstruí el núcleo con un módulo de núcleo de gadget (he probado con g_cdc y g_ether) en lugar de soporte integrado. No estoy seguro de si lo siguiente se debe a eso o simplemente no está sincronizado en mi publicación anterior. Si ejecuto ping en cualquier lado, los números TX y RX en realidad coinciden en ambos lados, pero el lado de Android los descarta por alguna razón.

Ifconfig del lado del host:

usb0      Link encap:Ethernet  HWaddr 12:23:34:45:56:67  
      inet addr:192.168.22.1  Bcast:192.168.22.255  Mask:255.255.255.0
      inet6 addr: fe80::1023:34ff:fe45:5667/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:33 errors:0 dropped:0 overruns:0 frame:0
      TX packets:734 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000 
      RX bytes:1140 (1.1 KiB)  TX bytes:37684 (36.8 KiB)

Lado de Android ifconfig:

usb0      Link encap:Ethernet  HWaddr 5E:89:C6:D8:BC:08  
      inet addr:192.168.22.2  Bcast:192.168.22.255  Mask:255.255.255.0
      inet6 addr: fe80::5c89:c6ff:fed8:bc08/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:734 errors:0 dropped:734 overruns:0 frame:0
      TX packets:33 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000 
      RX bytes:27408 (26.7 KiB)  TX bytes:1602 (1.5 KiB)

¡¡OTRA EDICIÓN!!

Después de usar arp en el lado del host e ip en el lado de Android para agregar entradas manualmente, los errores de Host de destino inalcanzable desaparecieron pero aún no hay respuesta de ping. Ejecuté Wireshark en el host y los mensajes del dispositivo no son correctos. Las direcciones mac que se muestran no se ven bien y el protocolo es desconocido, por lo que solo se muestra como 0x7aab. Después de mirar los datos reales en el mensaje, parece que hay dos bytes cero antepuestos al mensaje. Si se eliminaran, parece que todo se alinearía y funcionaría. ¿Alguien ha visto esto o sabe en qué parte del código se puede solucionar?

¡¡¡OTRA EDICIÓN!!!

Después de arrancar todo esta mañana, no creé las entradas ARP falsas y volví a ejecutar los pings. Según Wireshark, había un mensaje ARP proveniente del host y un mensaje desconocido proveniente del Droid, pero tenían longitudes idénticas. Después de examinar el contenido de los mensajes, el Droid también estaba enviando lo que parecía ser un mensaje ARP válido, pero se desplazó 2 bytes: dos bytes adicionales al principio y los dos últimos cortados.

¿Cuál es la topología entre dispositivos? dispositivo-dispositivo? ¿O estás pasando por un interruptor? si es de dispositivo a dispositivo, ¿qué tipo de cable estás usando?
Estoy usando el cable micro-usb estándar que viene con el teléfono, así que dispositivo-dispositivo.

Respuestas (1)

Parece que hay un problema con la alineación de bytes. Encontré esta publicación:

http://www.mail-archive.com/linux-omap@vger.kernel.org/msg20797.html

y en base a eso realizó los siguientes cambios en drivers/usb/gadget/u_ether.c:

257,258c257
< 
<   //skb_reserve(skb, NET_IP_ALIGN);
---
>   skb_reserve(skb, NET_IP_ALIGN);
513d511
<         int                     i=0;
599,606d596
< 
< if ((int)skb->data & 0x2) {
<   skb_push(skb, 2);
<   for (i=0; i<length; i++) {
<     skb->data[i] = skb->data[i+2];
<   }
< }
< 

Ahora puedo hacer ping en ambas direcciones a través del USB. Si alguien conoce una mejor manera de abordar esto, hágamelo saber, de lo contrario, seguiré con esto.