¿Cómo lograr el trasplante en serie en un dispositivo Android?

producto de transferencia es ligeramente neta: http://www.pinlue.com/article/2020/03/0706/469989490142.html

 

necesidades del proyecto, se den cuenta de envío de serie y reciben las funciones de Android, hay varias maneras de referencia.

1. Norma Android HAL capa pensamiento, funciones de la API se añaden al puerto serie del marco (similar a la aplicación del sensor en androide)

a. Asegúrese de que el controlador serie TTY basada jerarquía conductor puede leer correctamente, escritura, los datos de la encuesta, por supuesto, también puede escribir su propia unidad de caracteres a leer y escribir funciones de puerto serie.

b. Añadir devolución de llamada funciones de lectura y escritura de serie (capa de aplicación Linux c / c ++) en el BSP capa HAL

c. marco Android añadió capa jni, el análisis HAL módulo generado, entonces el paquete de funciones de devolución de llamada, .so generación biblioteca, para proporcionar capa de java.

d. Adición de interfaz de llamada remoto, añadir un AIDL marco de llamada remota utilizado

e. Añadir serviceManagement

2. sin pasar por el HAL, directamente a través de JNI para leer y escribir a la función de devolución de llamada, entonces el mismo.

3. pasar por el sistema androide, escrita directamente biblioteca JNI, llamar a las interfaces JNI directamente en la aplicación, transceptores de serie completo.

-------------------------------------------------- ----------------------------

Estos son los métodos disponibles, y aquí utilizo el tercer método simple mayoría, en el que el primer método es el más complicado, pero también es la manera estándar más androide, a continuación, voy a utilizar (bus CAN alcanzó un enigma en el trasplante ^ 0 ^), OK preámbulos, iniciar código de código de trabajo!

La primera es la capa de conductor, estoy usando un FSL placa de desarrollo, aquí Freescale nos ha ayudado a darse cuenta de la unidad, consulte ttymxc0, ttymxc1 en / dev / debajo .. . . Estos son los archivos del controlador después de cada puerto serie de la CPU, que puede probar echo "123"> / dev / mxctty0 se puede ver en la terminal de puerto serie se imprimirá "123."

Sin embargo, no nos dirigimos por lo que tomó las cosas de otras personas con, queremos analizar, de aprender, de culto, para ser copiado a. . . Parece que mi cosa favorita para hacer tal, bueno, aquí estoy brillando esta escritura controladores de dispositivos Linux explican un personaje impulsado, como nuestra barra de serie virtual.

Proporciona la misma funcionalidad con puerto serie, esta unidad que utilizo el bloqueo de manera de leer y escribir datos, mientras que la lectura de un libro, mientras que el aprendizaje, mientras que escribir su propio código, mientras que el aprendizaje de JNI, mientras que el aprendizaje de marco para Android, ¿por qué no?

En primer lugar, queremos dar de alta un personaje impulsado, e inicializar la cola, la inicialización del semáforo, inicializar variables, estructuras para asignar espacio de memoria, viejo sombrero. . . Un conductor de escritura sabe hacer estas cosas.

[Cpp] 

/ * * Módulo de controlador de dispositivo de función de carga /

int globalfifo_init (void)

{

resultado int;

globalfifo_devp = kmalloc (sizeof (struct globalfifo_dev), GFP_KERNEL);

if (! globalfifo_devp) {

resultar = -ENOMEM;

}

memset (globalfifo_devp, 0, sizeof (struct globalfifo_dev));

globalfifo_devp-> MDEV = mdev_struct;

resultar = misc_register (& (globalfifo_devp-> MDEV));

si (resultado <0)

return resultado;

init_MUTEX (y globalfifo_devp-> sem); / * inicializar el semáforo * /

init_waitqueue_head (y globalfifo_devp-> r_wait); / * cola de espera Cabeza de lectura de inicialización * /

init_waitqueue_head (y globalfifo_devp-> w_wait); / * inicializar la cabecera de la cola de espera de escritura * /

return 0;

}

Eso no, utilizado aquí miscdevice unidad, este sencillo y fácil de implementar, HOHO ~~ perezoso. Aquí se da la estructura global del espacio de memoria asignada, entonces la función de operación de la estructura vinculada a la estructura de nuestras variables globales, la última unidad miscdevice registrado.

[Cpp] 

/ * Estructura de dispositivo Globalfifo * /

struct globalfifo_dev

{

// struct cdev cdev; / * cdev estructura * /

struct MDEV miscdevice;

unsigned int current_len; / * fifo longitud de datos válido * /

sin firmar mem char [GLOBALFIFO_SIZE]; / * memoria global * /

struct semáforo sem; / * número de control concurrente de la señal * /

wait_queue_head_t r_wait; / * espera cabecera de la cola con el bloqueo de lectura * /

wait_queue_head_t w_wait; / * bloqueo escrito en la cabecera de la cola de espera * /

};

Vemos la definición de la estructura globalfifo aquí, aquí, por lo que en la función init, que necesitamos para inicializar el semáforo, inicializado a leer y escribir cabecera de la cola de espera. De lo contrario, vamos a tratar de obstruir el concepto de aquí.

Lo que su nombre sugiere, se ha quedado atascado en allí no más, de hecho, es en realidad se mueve, esperando el uso de bloqueo de aplicación de cola del dispositivo, cuando los procesos de usuario a los recursos del sistema de acceso, cuando no se puede acceder al recurso, que no quieren después se siguen produciendo, de manera que podamos bloquear por allá, puede estar seguro, podemos hacer que el proceso de ir a dormir, así que no pierda recursos de la CPU, sin embargo, esperar hasta que se puede acceder a los recursos, podemos despertar al bloqueados proceso, continúan dejarle ejecutarlo, si no hay lugar para despertarle, que en realidad "bloqueado" por allí.

Informar al, Echemos un vistazo al lado de lo que queremos lograr función de rendimiento

[Cpp] 

/ * Estructura de operaciones de archivo * /

estático const struct file_operations globalfifo_fops =

{

.owner = THIS_MODULE,

.read = globalfifo_read,

.WRITE = globalfifo_write,

.ioctl = globalfifo_ioctl,

.poll = globalfifo_poll,

.open = globalfifo_open,

.release = globalfifo_release,

};

He leído, escritura, abierta. . . . Y otras funciones, continúan analizando abajo.

[Cpp] 

struct globalfifo_dev * globalfifo_devp; / * puntero a la estructura del dispositivo * /

/ * Abrir archivo de la función * /

int globalfifo_open (struct nodo-i * i-nodo, struct file * filp)

{

/ * Puntero al archivo de configuración de dispositivo asignado al puntero de datos privados * /

filp-> private_data = globalfifo_devp;

return 0;

}

/ * Función de liberación del archivo * /

int globalfifo_release (struct nodo-i * i-nodo, struct file * filp)

{

return 0;

}

funciones de apertura y liberación no tienen nada que decir, pero en realidad, era bastante particular acerca de, por ejemplo, sólo podemos hacer que este dispositivo de un usuario para acceder, modelo de controlador de núcleo entonces podemos volver a abrir dentro de la función de hacer trampa, por lo general leemos va a ser ver una gran cantidad de tiempo en el diseño abierto funcionará a partir del recuento de referencia más 1, por lo que podemos controlar mejor el número de veces que se abre el dispositivo.

Pero aquí no hicimos nada, sólo hay que poner la variable estructura global se asigna a una variable miembro privada aquí en filp, por lo que podemos de nuevo la función en cada función de esta miembros privados, alienta la legibilidad del código , la liberación no hablar de ello.

[Cpp] 

/ * * Globalfifo función de lectura /

estática ssize_t globalfifo_read (struct file * filp, __user char * buf, size_t recuento,

loff_t * PPO)

{

ret int;

struct globalfifo_dev * dev = filp-> private_data; // puntero a la estructura del dispositivo obtenido

DECLARE_WAITQUEUE (espera, actual); // cola de espera se define

hacia abajo (y dev-> sem); // obtener el semáforo

add_wait_queue (y dev-> r_wait, y esperar); // cola de espera en la cabeza de lectura

/ * Espere a FIFO no está vacío * /

mientras que (dev-> current_len == 0)

{

si (filp-> f_flags y O_NONBLOCK)

{

K = - EAGAIN;

Ir a cabo;

}

__set_current_state (TASK_INTERRUPTIBLE); // cambiar el curso de un estado de sueño

arriba (y dev-> sem);

schedule (); programa de ejecución // otros procesos

si (signal_pending (actual))

// Si es porque el despertador

{

K = - ERESTARTSYS;

Goto out2;

}

hacia abajo (y dev-> sem);

}

/ * Copia en el espacio de usuario * /

Si (recuento> dev-> current_len)

count = dev-> current_len;

si (copy_to_user (buf, dev-> mem, recuento))

{

K = - EFAULT;

Ir a cabo;

}

más

{

memcpy (dev-> mem, dev-> mem + cuenta, dev-> current_len - recuento); // FIFO de datos hacia adelante

dev-> current_len - = recuento; // reducción de la longitud de datos válidos

printk (KERN_INFO "leer% d bytes (s), current_len:% d \ n", recuento, dev-> current_len);

wake_up_interruptible (y dev-> w_wait); // estela cola de escritura de espera

ret = count;

}

fuera:

arriba (y dev-> sem); // liberación de semáforos

OUT2:

remove_wait_queue (y dev-> w_wait, y espera); // espera cola se retira de la cabeza de la anexa

set_current_state (TASK_RUNNING);

Devolver la derecha;

}

Entonces esto es lo que leemos función, antes de realizar la lectura, hemos añadido a nuestra lista enlazada cola de la cola, a continuación, comprobar nuestra aficionado está vacía, si está vacío, entonces es nada que leer, así que deje latencia de la ciudad, cuando los bienes tienen nos leen, y luego despertar nuestra cola.

En primer lugar, la ciudad actual añadido a la cola de espera add_wait_queue (y dev-> r_wait, y espera);

Nada para leer, por lo que el proceso del sueño, en un despacho para ir a otras tareas

[Cpp] 

/ * Espere a FIFO no está vacío * /

mientras que (dev-> current_len == 0)

{

si (filp-> f_flags y O_NONBLOCK)

{

K = - EAGAIN;

Ir a cabo;

}

__set_current_state (TASK_INTERRUPTIBLE); // cambiar el curso de un estado de sueño

arriba (y dev-> sem);

schedule (); programa de ejecución // otros procesos

si (signal_pending (actual))

// Si es porque el despertador

{

K = - ERESTARTSYS;

Goto out2;

}

hacia abajo (y dev-> sem);

}

Este código es más crucial, ya que la función de escritura, cuando estamos llenos de piel de ante, que se producen atascos.

[Cpp] 

/ * * Globalfifo operaciones de escritura /

estática ssize_t globalfifo_write (struct file * filp, const char * buf __user,

size_t recuento, loff_t * PPO)

{

struct globalfifo_dev * dev = filp-> private_data; // puntero a la estructura del dispositivo obtenido

ret int;

DECLARE_WAITQUEUE (espera, actual); // cola de espera se define

hacia abajo (y dev-> sem); // obtener semáforo

add_wait_queue (y dev-> w_wait, y esperar); // espera para entrar en la cabeza de cola de escritura

/ * Espere a FIFO no está lleno * /

mientras que (dev-> current_len == GLOBALFIFO_SIZE)

{

si (filp-> f_flags y O_NONBLOCK)

// Si se trata de no bloqueo de acceso

{

K = - EAGAIN;

Ir a cabo;

}

__set_current_state (TASK_INTERRUPTIBLE); // cambiar el curso de un estado de sueño

arriba (y dev-> sem);

schedule (); programa de ejecución // otros procesos

si (signal_pending (actual))

// Si es porque el despertador

{

K = - ERESTARTSYS;

Goto out2;

}

hacia abajo (y dev-> sem); // obtener el semáforo

}

/ * Copiar desde el espacio de usuario al espacio del núcleo * /

Si (recuento> GLOBALFIFO_SIZE - dev-> current_len)

count = GLOBALFIFO_SIZE - dev-> current_len;

si (copy_from_user (dev-> mem + dev-> current_len, buf, recuento))

{

K = - EFAULT;

Ir a cabo;

}

más

{

dev-> current_len + = recuento;

printk (KERN_INFO "escrito% d bytes (s), current_len:% d \ n", recuento, dev-> current_len);

wake_up_interruptible (y dev-> r_wait); // espera de lectura de activación de colas

función de escritura con el tiempo se despertará nuestra cola, ya que al escribir en algo, y se puede leer, eso es todo, esta parte de la misma con nuestros transceptores de serie.

Otras características que no van a decir, OK, una vez completada la conducción, cargamos en, y luego prueba.

En primer lugar vamos a cat / dev / globalfifo

La obstrucción se produjo, se ha detenido en este momento vamos a abrir un terminal, a datos de escritura

echo "123"> / dev / globalfifo

Después de la escritura, de inmediato nos encontramos con el gato antes de que algo fuera, cada vez que leer todos los datos de salida.

==================================================

Aquí está nuestra JNI, en primer lugar debemos tener en claro lo que hacemos, encienda el dispositivo, la lectura del dispositivo, el último dispositivo no es el caso está cerrado, por lo que queremos lograr, al menos, estos tres API,

[Cpp] 

#define FIFO_CLEAR 0x01

#define BUFFER_LEN 20

#define GLOBALFIFO_PATH "/ dev / globalfifo"

int globalfifo_fd = -1;

JNIEXPORT jint JNICALL

Java_com_liujun_globalfifo_init (JNIEnv * env, jobject obj)

{

globalfifo_fd = abierto (GLOBALFIFO_PATH, O_RDONLY); // | O_NOBLOCK

si (globalfifo_fd! = -1)

{

__android_log_print (ANDROID_LOG_INFO, "JNI", "dispositivo abierto hecho.");

// Limpia la piel de ante

si (ioctl (globalfifo_fd, FIFO_CLEAR, 0) <0)

__android_log_print (ANDROID_LOG_INFO, "JNI", "error de aficionado claro!");

} else

__android_log_print (ANDROID_LOG_INFO, "JNI", "error de dispositivo abierto!");

}

Esta es nuestra función de inicialización define un descriptor de archivo global, función init sólo la acción abierta.

[Cpp] 

JNICALL JNIEXPORT jstring

Java_com_liujun_globalfifo_read (JNIEnv * env, jobject obj)

{

int nLea = 0;

Char buff [512] = "";

__android_log_print (ANDROID_LOG_INFO, "JNI", "leer");

nLea = read (globalfifo_fd, piel de ante, sizeof (buff));

si (nLea! = -1)

__android_log_print (ANDROID_LOG_INFO, "JNI", "===>% s", piel de ante);

retorno (* env) -> NewStringUTF (env, buff);

}

Esta API encapsulados función de lectura, a continuación, leer en buff java convierte en cadena reconocible, y finalmente vuelve a la capa de java de cadena de tipo de cadena.

[Cpp] 

JNIEXPORT jint JNICALL

Java_com_liujun_globalfifo_exit (JNIEnv * env, jobject obj)

{

cerrar (globalfifo_fd);

__android_log_print (ANDROID_LOG_INFO, "JNI", "cerca hecho!");

return 0;

}

Por último, esta es nuestra función de salida, llame al cierre para cerrar nuestro equipo. A continuación, escribir el archivo Android.mk, y, finalmente, compilar, globalfifo biblioteca

===========================================

A continuación, creamos un proyecto Android, importar la biblioteca JNI y definir la API nativa

[Cpp] 

init pública int nativo ();

Cadena nativa pública leer ();

pública de salida int nativo ();

estática {

System.loadLibrary ( "globalfifo");

}

A continuación, llame en los lugares apropiados. Provisto de tres botones, primero trate de abrir y leer, pulse el botón de lectura al abrir un hilo para leer los datos.

[Cpp] 

public class MyThread implementos Ejecutable {

public void run () {

// generada-Auto TODO Stub

while (true) {

tratar {

Thread.sleep (100); //

cadena = read ();

mensaje Mensaje = new Mensaje ();

message.what = 1;

handler.sendMessage (mensaje); // enviar un mensaje

} Catch (InterruptedException e) {

// bloque catch generada automáticamente TODO

e.printStackTrace ();

}

}

}

}

clase MyButtonListener implementos OnClickListener {

public void onClick (Ver v) {

si (v.getId () == R.id.start) {

en eso();

}

si (v.getId () == R.id.read) {

// cadena = read ();

//Toast.makeText(mContext, cuerda, Toast.LENGTH_SHORT) .show ();

Tema nuevo (nuevo MyThread ()) start ().;

}

si (v.getId () == R.id.close) {

salida();

}

}

}

Instalar apk, a continuación, ejecutar el programa, haga clic en Abrir y, a continuación, haga clic en la lectura, utilice el adb shell en el sistema, y ​​luego entró, y las cosas de escritura

echo "Jay Zhang"> dev / globalfifo

Puedo ver que hay Jay Zhang escupirla.

=================================================

Esto simula un puerto serie, y luego vamos a usar el proceso estándar de Android para completar el autobús desarrollo lata en los dispositivos Android.

Publicado 60 artículos originales · ganado elogios 52 · vistas 110 000 +

Supongo que te gusta

Origin blog.csdn.net/yihuliunian/article/details/104711595
Recomendado
Clasificación