First entry Android drive character device (iii)

Source: Internet
Author: User

Back when I was in college playing 51 single-chip computer, the first task of the teacher in the laboratory, is to design a 51 single-chip LED water lamp design, and realize several styles. The second task is to design a 51 microcontroller-based key control led flow lamp style design. Need to design hardware diagram, draw Protel circuit diagram, and design a PCB, to achieve Keil and Proteus of the joint, and then welded circuit board, to achieve its function. At that time do not understand, faith this a momentum, all kinds of Baidu, reading, at that time Guo Tianxiang 51 single-chip video super Fire, so the basic in his book and video learned, cattle, worship.

So, this is mainly about the simplest character drive of the key, by setting the connection to the pin as input, and reading its data register, to determine the key press, and then in the overall story about how the Android app calls the LED and key character device, and to achieve a simple function test (press the button, led lit, press release , led off). The next section, which is also the last section, focuses on some of the mechanisms of timer, interrupt, and competition in the character device. Nonsense a little more, into the subject:

1. Press the simplest driver:

<span style= "FONT-SIZE:14PX;" > #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/ input.h> #include <linux/platform_device.h> #include <linux/miscdevice.h> #include <mach/gpio.h > #include <linux/io.h> #include <mach/hardware.h> #include <linux/delay.h> #include <asm/ irq.h> #include <asm/uaccess.h>static struct class *buttondrv_class;static struct device *buttondrv_class_dev ; int major;volatile unsigned long *gpccon;volatile unsigned long *gpcdat;static int button_drv_open (struct inode *inode, s Truct file *file) {PRINTK (">>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>button_drv_open\n ") *GPCCON &= ~ (0xf< < (2*4)) |        (0xf<< (3*4))); *gpccon |= (0<< (2*4) | (0<< (3*4))); return 0;}               static int button_drv_read (struct file *filp, char __user *buf,                           size_t count, loff_t *offp) {PRINTK (">>>>>>>>>>>>>>&gt ; >>>>>>>>>>>>>>>>>>>>>>button_drv_read\n "); unsigned char k_val[2];int regval;regval = *gpcdat;k_val[0] = (Regval & (1<<2))? 1:0;K_VAL[1] = (Regval & (1<<3))? 1:0;PRINTK ("keyvalue[0]=%02x keyvalue[1]=%02x \ n", k_val[0],k_val[1]); Copy_to_user (buf, K_val, sizeof (K_val)); return sizeof (K_val);}           static struct File_operations Button_drv_fops = {. Owner = This_module,. Open = Button_drv_open, . read=button_drv_read,};static int Button_drv_init (void) {PRINTK (">>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>button    _drv_init\n "); Gpccon = (volatile unsigned long *) Ioremap (0xe0200080, 8); gpcdat= Gpccon + 1;if (! Gpccon) {Return-eio;} Major = Register_chrdev (0, "ButtoN_drv ", &button_drv_fops); Buttondrv_class = Class_create (This_module, "buttondrv"); Buttondrv_class_dev = Device_create (Buttondrv_class, NULL, MKDEV (Major, 0), NULL, "button"); return 0;} static void Button_drv_exit (void) {PRINTK (">>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>button_drv_exit\n "); unregister _chrdev (Major, "button_drv"); Device_unregister (Buttondrv_class_dev); Class_destroy (Buttondrv_class); Iounmap (Gpccon);} Module_init (Button_drv_init); Module_exit (Button_drv_exit); Module_license ("GPL"); </span><span style= "FONT-SIZE:24PX;" ></span>
A brief description of the demo

Button Here are two, one to Gpc12,gpc13, think of the earliest operation of the 51 single-chip microcomputer, the most simple test button is to do, the pin is set as input, and then read the status of the pin. Here s5pv210 the character device, here also try first.

First of all, the user or the upper-level app, for the function of the key demand, is simply by pressing the key, read the different state of the button, to do something. So, the key is to escalate an event or a message. Of course, different key types, the respective functions will also differ. Here is the most common button.

1. Ioremap: Map Its physical address 2 according to the PIN. Set as input:*gpccon &= ~ ((0xf<< (2*4)) |  (0xf<< (3*4))); *gpccon |= (0<< (2*4) | (0<< (3*4)));

3. In the Read function, read the value of the pin dat. Regval = *gpcdat;
K_val[0] = (Regval & (1<<2))? 1:0;
K_VAL[1] = (Regval & (1<<3))? 1:0;

2. Authoring of Jni shared libraries

2.1 Source Code

Button_test.cpp

<span style= "FONT-SIZE:14PX;"     > #define LOG_TAG "Rfidserialport" #include "utils/log.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include &lt ;fcntl.h> #include <termios.h> #include <errno.h> #include <string.h> #includ E <jni.h> #include "button_test.h" #include <ctype.h>static int fd_led=-1;static int Fd_button=-1;jint led_ Open (jnienv *env, Jobject thiz) {LOGE ("Led_open >>>>>>>>>>>>>>>> >>>>>>>>>> ") fd_led = open ("/dev/led ", O_RDWR), if (fd_led < 0) {LOGE (" open fd_  Lederror:%s\n ", Strerror (errno)); return-1;} return 0;} Jint Led_close (jnienv *env, Jobject thiz) {close (fd_led); return 0;} Jint Led_set (jnienv *env, Jobject thiz, Jint State) {if (state==1) write (fd_led, "1", 1), Elsewrite (fd_led, "0", 1); return 0;} Jint Button_open (JnieNV *env, Jobject thiz) {LOGE ("Button_open >>>>>>>>>>>>>>>>>> >>>>>>>> ") Fd_button = open ("/dev/button ", O_RDWR), if (Fd_button < 0) {LOGE (" open fd_  Buttonerror:%s\n ", Strerror (errno)); return-1;} return 0;} Jint Button_close (jnienv *env, Jobject thiz) {close (Fd_button); return 0;} Jint Button_get (jnienv *env, Jobject thiz, Jbytearray State) {LOGE ("Button_get >>>>>>>>> >>>>>>>>>>>>>>>>> "); Jbyte *jstate = env-> Getbytearrayelements (state, NULL); int Reply=-1;char value[2];memset (value,0,2); Reply=read (fd_button,value,2); LOGE ("value[0]=%02x value[1]=%02x", value[0],value[1]); if (reply<0) return-1;memcpy (jstate,value,2);env-> Releasebytearrayelements (state, jstate, 0); return 0;} Static Jninativemethod gmethods[] = {{"Led_open", "() i", (void*) led_open},{"Led_close", "() I", (void*) led_close},{"led _set "," (i) I ", (void*) led_set},{" button_open "," () i ", (void*) button_open},{" Button_close "," () i ", (void*) button_close},{" Button_get "," ([B) i ", (void*) Button_get},}; /* Register Several native methods for one class. *///noticestatic const char *classpathname = "com/example/button_test/buttontest"; static int registernatives (JNIEnv*    ENV) {Jclass clazz;    Clazz = Env->findclass (classpathname);        if (clazz = = NULL) {LOGE ("Native Registration unable to find class '%s '", classpathname);    return jni_false;    }else{Logi ("Find class sucess"); } if (Env->registernatives (Clazz, Gmethods, sizeof (gmethods)/sizeof (Gmethods[0])) < 0) {LOGE ("Registernat        Ives failed for '%s ', classpathname);    return jni_false; } return jni_true;} /* * **this is called by the VM when the shared library is first loaded.    * */jint jni_onload (javavm* vm, void* reserved) {jint result =-1;    jnienv* env = NULL;    Logi ("Jni_onload"); if (vm->getenv (void * *) &env, jni_version_1_4)! = Jni_OK) {LOGE ("error:getenv failed");    Goto bail;        } if (registernatives (env) = jni_true) {LOGE ("Error:registernatives failed");    Goto bail; } result = Jni_version_1_4;bail:return result;} </span><span style= "FONT-SIZE:18PX;" > </span>
button_test.h

<span style= "FONT-SIZE:14PX;" > #include <jni.h> #ifndef _included_button_test#define _included_button_test#ifdef __cplusplusextern "C" {#  Endifjint Led_open (jnienv *env, Jobject thiz); Jint led_close (jnienv *env, Jobject thiz); Jint Led_set (JNIEnv *env, Jobject Thiz,int stat); Jint Button_open (jnienv *env, Jobject thiz); Jint button_close (jnienv *env, Jobject thiz); Jint Button_get ( JNIEnv *env, Jobject thiz,jbytearray State); #ifdef __cplusplus} #endif #endif</span><span style= "font-size : 18px; " ></span>

Android.mk

<span style= "FONT-SIZE:14PX;" >local_path:= $ (call My-dir) include $ (clear_vars) Local_module_tags: = englocal_src_files:= Button_test.cpplocal_ Shared_libraries: = libutils libhardware libdl   local_c_includes + =         $ (jni_h_include)   local_module:= Libbuttontestlocal_prelink_module: = Falseinclude $ (build_shared_library) </span>


2.2 Simple analysis of source code

Recall the previous test led program, you can know, led mainly call three methods, open, write, close, with the button is also three, open, read, close.

Now that native needs to provide 6 methods to the top app, how can it be implemented?

Here you need to know the JNI (Java Native Interface), want to learn more about its mechanism, can see "in-depth understanding of Android Volume" chapter II (if you need some information, you can leave a message). Here is the main way to do, specific principles of things, you need to learn afterwards. In simple terms, JNI is a bridge between native (c, C + +) and Java. At the same time, be sure to pay attention to the rigor of the code, error prone. JNI has both static and dynamic registration methods, which are used for dynamic registration.

Button_test.cpp

First look from the back:

jni_onload: Dynamic registration is used, in the Java call system.loadlibrary method, will call Jni_onload, in this function, the main call registernatives method.

registernatives: 1. Clazz = Env->findclass (Classpathname) This is the associated native and Java class, the main, the path is wrong, after Java loaded So, there will be no way to find the native method error.

2. Env->registernatives (Clazz, Gmethods, sizeof (gmethods)/sizeof (Gmethods[0])) < 0 This is primarily an association of registered functions, Can be connected to establish a always-bidirectional mapping from the native method to the Java class method.

Jninativemethod: This is the method mapping table, where you pay attention to the signature information of the parameter and the return value. See this, the basic framework has come out.

Button_test.h

#ifdef __cplusplus
extern "C" {
#endif


#ifdef __cplusplus
}
#endif

Because this is a C + + code, this part is added to the compatibility problem with C.

Android.mk

The previous section has been introduced, where the include $ (build_shared_library), is to compile the module into a dynamic shared library.

Then, if you compile under the Android environment or the NDK, the libbuttontest.so will be generated.


3 Writing the App

Here there are two main parts, part of the import native function, part call native method.

Buttontest.java

Package Com.example.button_test;import Android.content.context;import Android.util.log;public class ButtonTest { static{system.loadlibrary ("Buttontest");} public native int Led_open ();p ublic native int led_close ();p ublic native int led_set (int. state);p ublic native int button_o Pen ();p ublic native int button_close ();p ublic native int button_get (byte state[]);}
Here System.loadlibrary ("Buttontest"), do not need to writelibbuttontest.so. The following are the native functions in the map table, note the consistency of the parameters and the return values.

Package com.example.button_test; is consistent with the static const char *classpathname = "Com/example/button_test/buttontest" in JNI.

mainactivity. java

Package Com.example.button_test;import Android.support.v7.app.actionbaractivity;import Android.os.Bundle;import Android.util.log;import android.view.menu;import android.view.menuitem;import com.example.button_test. Buttontest;public class Mainactivity extends Actionbaractivity {buttontest test=new buttontest ();//Notice byte state[]=    {0,0};int flag=1;        @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (R.layout.activity_main);        Test.led_open ();                Test.button_open ();        for (;;)        {Test.button_get (state);        if (state[1] = = 1 | | state[0] = = 1) {test.led_set (1);            flag++;        if (flag>20) break;        } else {test.led_set (0);        flag++;        if (flag>20) break;        } try {Thread.Sleep (500);        } catch (Interruptedexception e) {e.printstacktrace ();        }} test.button_close ();    Test.led_close (); } @Override Public boolean Oncreateoptionsmenu (Menu menu) {//Inflate the menu, this adds items to the Actio        n Bar if it is present.        Getmenuinflater (). Inflate (R.menu.main, menu);    return true; } @Override public boolean onoptionsitemselected (MenuItem Item) {//Handle Action Bar item clicks here.  The action bar would//automatically handle clicks on the Home/up button, so long/As you specify a parent        Activity in Androidmanifest.xml.        int id = item.getitemid ();        if (id = = r.id.action_settings) {return true;    } return super.onoptionsitemselected (item); }    }
Here's what you need to know about eclipse and how to create a new Android project.

1.import Com.example.button_test. Buttontest; Here import buttontest to Local

2.ButtonTest test=new buttontest (); Defines a buttontest class.

3. Call the native method in the function.


Note: This whole process, it is impossible to write one at a time, where the main use of printing debugging means, for some of the more difficult to solve the problem, it may be necessary to use some tools. The entire process:

1. Put two drive numbers, push Ko to Android device, Insmod load two drivers, and change the permissions of its device node, chmod 777/dev/led && chmod 777 Dev/button, Otherwise, the open method in JNI will fail.

2. Write the JNI library. Push the resulting so library to System/lib, and of course you can put it under your Eclipse Project libs/armeabi/, which is generally recommended under the project.

3. Write the application. Running the application, you can see, press the button light on, release the light off.




Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

First entry Android drive character device (iii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.