驅動模型 從底層驅動到HAL到JNI到app到雲端服務器

app通過二維碼開關掃描請求雲服務器對蜂鳴器的開或關
        概述:arm端建立服務與雲端連接等待雲服務器的命令,手機掃描二維碼通過二維碼裏面的設備號和開或者關信息發送到雲端服務器,雲端服務器根據設備號找到對應的arm端發送相應的開或關命令,從而實現手機APP雲端控制
1.硬件原理圖  
蜂鳴器連接(GPD0_1)管腳
2.芯片手冊
蜂鳴器的控制地址爲 int id = 0xe02000a0;
配置爲輸出端口 (*(int *)id)&(~(0xf<<4)); (*(int *)id)&(0x1<<4);
蜂鳴器數據地址爲 int add = 0xe02000a4;
蜂鳴器啓動  (*(int *) add )|(0x1<<1));
蜂鳴器停止 (*(int *) add )&(~(0x1<<1));


3.編寫驅動
        buzz_drv.c代碼編寫
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h> /* for class_create() and device_create() */
#include <linux/cdev.h> /* for cdev */
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/io.h>
static int num = 1;
static int major = 0;
struct buzz_cdev {
struct cdev cdev;
struct class *buzz_class;
struct device *buzz_device;
//...
int buzz_val;
};
struct buzz_cdev *buzz_dev =NULL;
/* buzz 控制寄存器的物理地址*/
#define BUZZ_PHY_GPC0BASE 0xe02000a0
/*(GPD0_1)管腳 所有爲8 一個int4位*/
#define BUZZ_PHY_GPC0LEN 8
/* buzz 控制寄存器的虛擬地址 */
volatile unsigned long *gpd0con =NULL;
volatile unsigned long *gpd0dat = NULL;
/*打開外設 */
static int buzz_open (struct inode *inode, struct file *file)
{
//外設的初始化
gpd0con = ioremap(BUZZ_PHY_GPC0BASE, BUZZ_PHY_GPC0LEN);
if(!gpd0con){
printk(KERN_ERR "ioremap buzz physical address failed.!\n");
return -ENOMEM;
}
gpd0dat = gpd0con +1; //指針+1,表示4個字節 dpd0_1管腳
/*將GPd0_1配置成輸出功能 */
*gpd0con = *gpd0con & ~(0xff<<4);
*gpd0con = *gpd0con & (0x1<<4);
return 0;
}
static ssize_t buzz_read (struct file * file, char __user *buf, size_t count, loff_t *offsize)
{
printk("func: %s() line: %d\n", __func__, __LINE__);
return count;
}
static ssize_t buzz_write(struct file *file, const char __user *buf,
size_t bytes, loff_t *off)
{
int ker_val, ret=-1;
ret = copy_from_user(&ker_val, buf, sizeof(int));
if(ret < 0) {
printk("buzz_write() failed!\n");
goto out;
}
if(ker_val == 1) { //打開蜂鳴器
*gpd0dat |= 1<<1;
} else { //關閉蜂鳴器
*gpd0dat &= ~(1<<1);
}
return bytes;
out:
return ret;
}
static int buzz_close(struct inode * inode, struct file * file)
{
// *gpd0dat &= ~(1<<1); //關閉蜂鳴器
iounmap(gpd0con);
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE, /* 模塊的自動計數 */
.open = buzz_open,
.read = buzz_read,
.write = buzz_write,
.release = buzz_close,
};
static int buzz_setup_cdev(void)
{
int err, devno = MKDEV(major,0);
/* 初始化cdev*/
cdev_init(&buzz_dev->cdev,&fops);
buzz_dev->cdev.owner = THIS_MODULE;
buzz_dev->cdev.ops = &fops;
/* 向系統註冊*/
err = cdev_add(&buzz_dev->cdev, devno, 1);
if(err < 0) {
printk(KERN_ERR "Added cdev device failed.\n");
return err;
}
return 0;
}
static int __init buzz_init(void)
{
dev_t devno = MKDEV(major, 0);
int ret = -1;
buzz_dev = (struct buzz_cdev *)kmalloc(sizeof(struct buzz_cdev), GFP_KERNEL);
if(!buzz_dev) {
ret = -ENOMEM;
goto out_err_0;
}
/* 向系統申明佔用設備號或讓系統自動分配設備號*/
if(major) {
ret = register_chrdev_region(devno, 1, "buzz");
} else {
ret = alloc_chrdev_region(&devno,0,1,"buzz");
major = MAJOR(devno);
}
if(ret < 0) {
printk(KERN_ERR "register chrdev device number failed\n");
goto out_err_1;
}
ret = buzz_setup_cdev();
if( ret < 0) {
goto out_err_2;
}
/* 自動創建設備節點*/
buzz_dev->buzz_class = class_create(THIS_MODULE, "buzz_class");
if(IS_ERR(buzz_dev->buzz_class)) {
printk("class_create() failed");
goto out_err_3;
}
buzz_dev->buzz_device = device_create(buzz_dev->buzz_class, NULL,
MKDEV(major, 0), NULL, "buzz"); //正常情況下系統會自動創建/dev/buzz
if(IS_ERR(buzz_dev->buzz_device)) {
printk("device_create() failed");
goto out_err_4;
}
printk("buzz driver has installed.\n");
/* 正常返回*/
return 0;
out_err_4:
class_destroy(buzz_dev->buzz_class);
out_err_3:
cdev_del(&buzz_dev->cdev);
out_err_2:
unregister_chrdev_region(MKDEV(major, 0),1);
out_err_1:
kfree(buzz_dev);
out_err_0:
return ret;
}
static void __exit buzz_exit(void)
{
device_destroy(buzz_dev->buzz_class,MKDEV(major, 0));
class_destroy(buzz_dev->buzz_class);
cdev_del(&buzz_dev->cdev);
unregister_chrdev_region(MKDEV(major, 0),1);
return;
}
module_param(num, int, S_IRWXU);
module_init(buzz_init); /* 驅動的入口*/
module_exit(buzz_exit); /* 驅動的出口*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("[email protected]");
MODULE_DESCRIPTION("This is cdev demo driver");
        Makefile編寫

ifeq ($(KERNELRELEASE),)
KERNELDIR = /home/george/src_210/linux-3.0.8-FS210
PWD =$(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.so *.o *.ko .tmp_versions *.mod.c *.order *.symvers
else
obj-m :=buzz_drv.o
endif

創建自己的sh文件如infrare.sh:                                                                                        # ! /system/bin/sh
           insmod /device.ko                                                                                                              insmod /control.ko                                                                                                              mknod /dev/controler c 240 0
修改init.rc最後寫入自己的腳本                                                                                            service infrare /system/bin/sh /data/infrare.sh                                                                               user root                                                                                                                             soneshot
這樣就可以使用自己的驅動了另外在init.rc中的總結init中可以執行insmod命令但是不能執行mknod的,解釋是這樣的init.rc裏所有可用的command都定義在system/core/init/keyword.h裏,默認是不包含mknod的。事實上,Android的init進程會通過kenel的uevent來自動創建設備節點(見system/core/init/devices.c裏的make_device()函數)。


4.硬件抽象層
        buzz_hal.h
#ifndef __BUZZ_HAL_H__
#define __BUZZ_HAL_H__
#include <hardware/hardware.h>
#define BUZZ_HAL_MODULE_ID "buzz_hal"
//擴展device對象和module對象
struct buzz_hw_module_t{ //自由定義
//繼承父類
struct hw_module_t common; //一定要在第一個位置,必須叫做common
//進行擴展--可選的
//char *name ;
//void (*test)();
};
struct buzz_hw_device_t{
//繼承父類
struct hw_device_t common; //一定要在第一個位置,必須叫做common
//進行擴展--可選的
int (*open)(void);
int (*switch_on)(int on);
};
#endif
        buzz_hal.c


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "buzz_hal.h"
#define LOG_TAG "buzz_hal_log"
#include <utils/Log.h>
static int buzz_fd = -1;
//去操作硬件
int buzz_hal_device_close(struct hw_device_t* device)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
if(device != NULL)
{
free(device);
}
close(buzz_fd);
return 0;
}
int buzz_hal_device_open(void)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
buzz_fd = open("/dev/buzz", O_RDWR);
if(buzz_fd < 0)
{
LOGE("open buzz : %s\n", strerror(errno));
return -1;
}
return 0;
}
int buzz_hal_device_switch(int on)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
int ret = -1;
ret = write(buzz_fd, &on, 4);
if(ret < 0)
{
LOGE("write buzz off : %s\n", strerror(errno));
return -1;
}
return 0;
}
//如果該函數被調用,傳遞第三個參數爲一個一級指針,該指針就會等於mydev
int buzz_module_open(const struct hw_module_t* module, const char* id,
struct hw_device_t** device)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
//構建device對象
struct buzz_hw_device_t *mydev = NULL;
//動態去創建
mydev = (struct buzz_hw_device_t *)malloc(sizeof(struct buzz_hw_device_t));
if(mydev == NULL)
{
LOGE("malloc for buzz_hw_device_t error\n");
return -1;
}
//初始化
mydev->common.tag = HARDWARE_DEVICE_TAG;
mydev->common.version = 1;
mydev->common.module = (struct hw_module_t*)module;
mydev->common.close = buzz_hal_device_close;
//初始化擴展的部分
mydev->open = buzz_hal_device_open;
mydev->switch_on = buzz_hal_device_switch;
//將當前mydev交給jni
*device = (struct hw_device_t*)mydev;
return 0;
}
struct hw_module_methods_t my_module_methods = {
open : buzz_module_open,
};
//實例化module對象
// p->common.methods->open();
struct buzz_hw_module_t HMI = { //變量名一定要是HMI
//初始化
common :{
tag : HARDWARE_MODULE_TAG,
version_major : 1,
version_minor : 0,
id : BUZZ_HAL_MODULE_ID,
name : "this is a simple buzz hal hahah",
author : "[email protected]",
methods : &my_module_methods,
},
};



        Android.mk



LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := \
libcutils
LOCAL_SRC_FILES:= buzz_hal.c
LOCAL_MODULE := buzz_hal.default
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)


5.JNI層
        buzz_jni.cpp

#define LOG_TAG "buzz_jni_log"
#include <utils/Log.h>
#include "jni.h"
// 對於hal的頭文件, 典型的做法: libhardware/hardware/buzz_hal.h
//其他的代碼去引用的時候: #include <hardware/buzz_hal.h>
/*
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
$(LOCAL_PATH)/../buzz_hal
*/
#include "buzz_hal.h"
//聲明兩個指針
static struct buzz_hw_module_t *pModule;
static struct buzz_hw_device_t *pDevice;
/*
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
*/
jint open_buzz(JNIEnv *env, jobject thiz)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
//加載hal.so
jint ret = -1;
//如果在代碼中使用了該函數,編譯的時候需要連接 libhardware
ret = hw_get_module(BUZZ_HAL_MODULE_ID, (const struct hw_module_t * *)&pModule);
if(ret == 0)
{
if(pModule != NULL)
{
//調用module中的open方法
//p->common.methods->open();
pModule->common.methods->open(&pModule->common,NULL, (struct hw_device_t**)&pDevice);
if(pDevice != NULL)
{
//調用device中的方法
ret = pDevice->open();
if(ret < 0)
{
LOGE("open device error\n");
return -1;
}
}
}
}else{
LOGE("hw_get_module error\n");
return -2;
}
return 0;
}
jint buzz_off(JNIEnv *env, jobject thiz)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
jint ret = -1;
if(pDevice != NULL)
{
ret = pDevice->switch_on(0);
if(ret < 0){
return -1;
}
}
return 0;
}
jint buzz_on(JNIEnv *env, jobject thiz)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
jint ret = -1;
if(pDevice != NULL)
{
ret = pDevice->switch_on(1);
if(ret < 0){
return -1;
}
}
return 0;
}
jint close_buzz(JNIEnv *env, jobject thiz)
{
LOGD("-----^_^ %s--------\n", __FUNCTION__);
if(pDevice != NULL)
{
pDevice->common.close((struct hw_device_t *)pDevice);
}
return 0;
}
/*
package com.android.lowlevel;
public class BuzzNative{
native int openDev()
native int devOn()
native int devOff()
native int closeDev()
}
*/
//構建一個映射表
static JNINativeMethod myMethods[] = {
//java方法的名字一定要和java代碼中的名字保持一致
{"openDev", "()I", (void *)open_buzz},
{"devOn", "()I", (void *)buzz_on},
{"devOff", "()I", (void *)buzz_off},
{"closeDev", "()I", (void *)close_buzz},
};
//實現jni_onload
jint JNI_OnLoad(JavaVM * vm,void * reserved)
{
LOGE("--------JNI_OnLoad----------\n");
jint ret = -1;
//1,獲取到dvm的環境變量對象,是一個工具集合, 有操作jni空間代碼的各種方法
JNIEnv *env = NULL;
//獲取到env, 並且測試當前的jni版本是否是1.4
ret = vm->GetEnv((void * * )&env, JNI_VERSION_1_4);
if(ret != JNI_OK)
{
//表示出錯了
LOGE("vm->GetEnv error\n");
return -1;
}
//2,通過環境變量對象提供去註冊映射表對象
//爲java方法提供類名
jclass myCls = env->FindClass("com/android/lowlevel/BuzzNative");
if(myCls == NULL)
{
LOGE("env->FindClass error\n");
return -1;
}
ret = env->RegisterNatives(myCls, myMethods, sizeof(myMethods)/sizeof(myMethods[0]));
if(ret < 0)
{
LOGE("env->RegisterNatives error\n");
return -1;
}
//JNI_OnLoad正常返回
return JNI_VERSION_1_4;
}
        Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= libbuzz_jni
LOCAL_SRC_FILES:= buzz_jni.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhardware
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
$(LOCAL_PATH)/../buzz_hal
include $(BUILD_SHARED_LIBRARY)

6.arm端上層
        com.android.lowlevel.BuzzNative.java
package com.android.lowlevel;
public class BuzzNative {
static{
System.loadLibrary("buzz_jni");
}
public native int openDev();
public native int devOn();
public native int devOff();
public native int closeDev();
}

        com.android.buzz.service.BuzzManagerI.aidl

package com.android.buzz.service;
interface BuzzManagerI {
int openDev();
int devOn();
int devOff();
int closeDev();
}

        com.android.buzz.service.BuzzManagerService.java

package com.android.buzz.service;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import com.android.lowlevel.BuzzNative;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class BuzzManagerService extends Service {
public static final String BUZZ_DEVICE_ID = "fs210_1507_11_arm_buzz";
public static final String IP = "120.25.120.198";
public static final int port = 5010;
private ClientThread mClientThread;
@Override
public IBinder onBind(Intent intent) {
return BuzzManagerBinder.getInstance();
}
@Override
public void onCreate() {
super.onCreate();
mClientThread = new ClientThread(BuzzManagerBinder.getInstance(), IP, port);
mClientThread.start();
}
@Override
public void onDestroy() {
super.onDestroy();
mClientThread.stop();
}
private static class commandThread implements Runnable{
private String command;
private BuzzManagerBinder mBinder;
private OutputStream os;
public commandThread(String common,BuzzManagerBinder mBinder,OutputStream os) {
super();
this.mBinder = mBinder;
this.command = common;
this.os = os;
}
public void start(){
new Thread(this).start();
}
@Override
public void run() {
if(command!=null){
if(command.contains(":")&&command.indexOf("command")==0){
String strs[] = command.split(":");
if(strs.length==2){
try {
int ret = mBinder.openDev();
if(ret == 0){
if(strs[1].equals("on")){
mBinder.devOn();
}else if(strs[1].equals("on")){
mBinder.devOff();
}
mBinder.closeDev();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
}
}
public static class ClientThread implements Runnable{
private static final Object LOCK = new Object();
private BuzzManagerBinder mBinder;
private boolean flages = false;
private Socket mSocket;
private String ip;
private int port;
private OutputStream os;
public ClientThread(BuzzManagerBinder mBinder,String ip,int port) {
super();
this.mBinder = mBinder;
this.ip = ip;
this.port = port;
}
public void start(){
synchronized (LOCK) {
if(!flages){
flages = true;
new Thread(this).start();
}
}
}
public void stop(){
synchronized (LOCK) {
if(os!=null){
try {
os.write("close".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
flages = false;
}
}
@Override
public void run() {
try {
mSocket = new Socket(InetAddress.getByName(ip), port);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if(mSocket != null){
try {
InputStream is = mSocket.getInputStream();
os = mSocket.getOutputStream();
os.write(("deviceId:"+BUZZ_DEVICE_ID).getBytes());
while (flages) {
byte[] buffer = new byte[1024*2];
int len = is.read(buffer);
String str = new String(buffer, 0, len).trim();
if("close".equals(str)){
flages = false;
}else{
new commandThread(str, mBinder, os).start();
}
}
os.close();
is.close();
if(!mSocket.isClosed()){
mSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static class BuzzManagerBinder extends BuzzManagerI.Stub{
private static BuzzManagerBinder mBinder;
private int openNumber = 0;
private int openDev=-1;
private int closeDev = 0;
private BuzzNative mBuzzNative;
public BuzzManagerBinder() {
super();
mBuzzNative = new BuzzNative();
}
public static BuzzManagerBinder getInstance(){
if(mBinder==null){
mBinder = new BuzzManagerBinder();
}
return mBinder;
}
@Override
public int openDev() throws RemoteException {
if(openNumber==0){
openDev = mBuzzNative.openDev();
}
openNumber++;
return openDev;
}
@Override
public int devOn() throws RemoteException {
if(openDev==0){
return mBuzzNative.devOn();
}
return -1;
}
@Override
public int devOff() throws RemoteException {
if(openDev==0){
return mBuzzNative.devOff();
}
return -1;
}
@Override
public int closeDev() throws RemoteException {
if(openDev==0){
openNumber--;
if(openNumber==0){
closeDev = mBuzzNative.closeDev();
}
return closeDev;
}
return -1;
}
}
}

         BootReciver.java

package com.android.buzz.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootReciver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(Intent.ACTION_BOOT_COMPLETED.equals(action)
||"com.android.buzz.SERVICE_START".equals(action)){
if(!BuzzManagerService.isLive){
Intent startServiceIntent = new Intent(context, BuzzManagerService.class);
context.startService(startServiceIntent);
}
}
}
}

         AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.buzz"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="com.android.buzz.service.BuzzManagerService"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service android:name="com.android.buzz.service.BuzzManagerService"
android:permission="com.android.buzz.service.BuzzManagerService"
android:exported="true">
<intent-filter >
<action android:name="com.android.buzz.service.BuzzManagerService"/>
</intent-filter>
</service>
<receiver android:name="com.android.buzz.service.BootReciver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="com.android.buzz.SERVICE_START"/>
</intent-filter>
</application>
</manifest>

         Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/com/android/buzz/service/BuzzManagerI.aidl
LOCAL_PACKAGE_NAME := BuzzService
LOCAL_CERTIFICATE := platform
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
7.二維碼處理
        ZxingUtil.java
package com.android.zxing;
import java.io.FileNotFoundException;
import java.util.Hashtable;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;
public class ZxingUtil {
public static String getStringFromBitmap(Bitmap bitmap){
Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
RGBLuminanceSource mLuminanceSource = new RGBLuminanceSource(bitmap);
Binarizer binarizer = new HybridBinarizer(mLuminanceSource);
BinaryBitmap mBinaryBitmap = new BinaryBitmap(binarizer);
QRCodeReader mCodeReader = new QRCodeReader();
try {
Result r= mCodeReader.decode(mBinaryBitmap, hints);
return r.getText();
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ChecksumException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static Bitmap getBitmapFromString(BitmapDrawable bitmapDrawable,String string,int wh){
if(wh<10){
throw new IllegalArgumentException("ͼƬ̫С");
}
Bitmap bitmap = Bitmap.createBitmap(wh, wh, Bitmap.Config.ARGB_8888);
if(bitmapDrawable!=null){
bitmapDrawable.setBounds(0, 0, wh, wh);
Canvas mCanvas = new Canvas(bitmap);
bitmapDrawable.draw(mCanvas);
}
// QRCodeWriter mCodeWriter = new QRCodeWriter();
MultiFormatWriter mCodeWriter = new MultiFormatWriter();
try {
Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix mBitMatrix = mCodeWriter.encode(string, BarcodeFormat.QR_CODE, wh, wh,hints);
int[] pixels = new int[wh * wh];
bitmap.getPixels(pixels, 0, wh, 0, 0, wh, wh);
for (int y = 0; y < wh; y++) {
for (int x = 0; x < wh; x++) {
if (mBitMatrix.get(x, y)) {
pixels[y * wh + x] = 0xdd222222&pixels[y * wh + x];
} else {
pixels[y * wh + x] = 0x88ffffff&pixels[y * wh + x];
}
}
}
bitmap.setPixels(pixels, 0, wh, 0, 0, wh, wh);
} catch (WriterException e) {
e.printStackTrace();
}
return bitmap;
}
public static class RGBLuminanceSource extends LuminanceSource {
private final byte[] luminances;
public RGBLuminanceSource(String path) throws FileNotFoundException {
this(loadBitmap(path));
}
public RGBLuminanceSource(Bitmap bitmap) {
super(bitmap.getWidth(), bitmap.getHeight());
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
// In order to measure pure decoding speed, we convert the entire image
// to a greyscale array
// up front, which is the same as the Y channel of the
// YUVLuminanceSource in the real app.
luminances = new byte[width * height];
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
int pixel = pixels[offset + x];
int r = (pixel >> 16) & 0xff;
int g = (pixel >> 8) & 0xff;
int b = pixel & 0xff;
if (r == g && g == b) {
// Image is already greyscale, so pick any channel.
luminances[offset + x] = (byte) r;
} else {
// Calculate luminance cheaply, favoring green.
luminances[offset + x] = (byte) ((r + g + g + b) >> 2);
}
}
}
}
@Override
public byte[] getRow(int y, byte[] row) {
if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException(
"Requested row is outside the image: " + y);
}
int width = getWidth();
if (row == null || row.length < width) {
row = new byte[width];
}
System.arraycopy(luminances, y * width, row, 0, width);
return row;
}
// Since this class does not support cropping, the underlying byte array
// already contains
// exactly what the caller is asking for, so give it to them without a copy.
@Override
public byte[] getMatrix() {
return luminances;
}
}
private static Bitmap loadBitmap(String path) throws FileNotFoundException {
Bitmap bitmap = BitmapFactory.decodeFile(path);
if (bitmap == null) {
throw new FileNotFoundException("Couldn't open " + path);
}
return bitmap;
}
}

8.手機APP
        MainActivity.java
package com.buzzapp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Hashtable;
import com.android.buzz.R;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
public static final String BUZZ_DEVICE_ID_ON = "fs210_1507_11_arm_buzz:on";
public static final String BUZZ_DEVICE_ID_OFF = "fs210_1507_11_arm_buzz:off";
public static final String IP = "120.25.120.198";
private static final int port = 5010;
public Bitmap getBitmapFromString(String string,int len){
Bitmap bitmap = Bitmap.createBitmap(len, len, Bitmap.Config.ARGB_8888);
int[] pixels = new int[len*len];
MultiFormatWriter qrCodeWriter = new MultiFormatWriter();
try {
Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix mBitMatrix = qrCodeWriter.encode(string, BarcodeFormat.QR_CODE, len, len,hints);
for(int y=0;y<len;y++){
for(int x=0;x<len;x++){
if(mBitMatrix.get(x, y)){
pixels[y*len+x] = 0xff000000;
}else{
pixels[y*len+x] = 0xffffffff;
}
}
}
bitmap.setPixels(pixels, 0, len, 0, 0, len, len);
} catch (WriterException e) {
e.printStackTrace();
}
return bitmap;
}
public class SendMsgThread implements Runnable{
private String msg;
public SendMsgThread(String msg) {
super();
this.msg = msg;
}
public void start(){
new Thread(this).start();
}
@Override
public void run() {
try {
Socket mSocket = new Socket(InetAddress.getByName(IP), port);
OutputStream os = mSocket.getOutputStream();
os.write(msg.getBytes());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
os.write("close".getBytes());
os.flush();
os.close();
mSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private TextView msg;
private Button scan,buzz,unbuzz;
private ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
msg = (TextView) findViewById(R.id.textView1);
scan = (Button) findViewById(R.id.button_scan);
scan.setOnClickListener(this);
buzz = (Button) findViewById(R.id.button_buzz);
buzz.setOnClickListener(this);
unbuzz = (Button) findViewById(R.id.button_unbuzz);
unbuzz.setOnClickListener(this);
image = (ImageView) findViewById(R.id.image);
image.setVisibility(View.GONE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case SCAN_REQUEST_CODE:
if(resultCode == RESULT_OK){
String str = data.getStringExtra("result");
msg.setText(str);
new SendMsgThread(str.trim()).start();
}else{
msg.setText("掃描失敗");
}
break;
default:
break;
}
}
public static final int SCAN_REQUEST_CODE = 0x1001;
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.button_scan:
Intent intent = new Intent("com.android.SCAN_ACTION");
intent.setClassName("com.ericssonlabs", "com.zxing.activity.CaptureActivity");
startActivityForResult(intent, SCAN_REQUEST_CODE); break;
case R.id.button_buzz:
image.setImageBitmap(getBitmapFromString(BUZZ_DEVICE_ID_ON, 300));
image.setVisibility(View.VISIBLE);
break;
case R.id.button_unbuzz:
image.setImageBitmap(getBitmapFromString(BUZZ_DEVICE_ID_OFF, 300));
image.setVisibility(View.VISIBLE);
break;
default:
break;
}
}
}

        Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/com/android/buzz/service/BuzzManagerI.aidl
LOCAL_PACKAGE_NAME := BuzzAPP
LOCAL_CERTIFICATE := platform
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
# Added for source code compile start 爲jar起一個別名
LOCAL_STATIC_JAVA_LIBRARIES := \
jarlibzxing \
jarlibv4
include $(BUILD_PACKAGE)
# Added for source code compile start 冒號前面爲jar別名,後面爲jar文件的實際路徑
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
jarlibzxing:libs/zxing.jar \
jarlibv4:libs/android-support-v4.jar
include $(BUILD_MULTI_PREBUILT)
include $(call all-makefiles-under,$(LOCAL_PATH))

9.雲服務器端
        ClouceBuzzService.java
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class ClouceBuzzService implements Runnable {
public static final String DEVICE_ID_STRING = "deviceId";
public static String getValue(String str) {
if (str.contains(":")) {
String[] array = str.split(":");
if (array.length == 2) {
return array[1];
}
}
return null;
}
public static String getKey(String str) {
if (str.contains(":")) {
String[] array = str.split(":");
if (array.length == 2) {
return array[0];
}
}
return null;
}
/**
* @param args
*/
public static void main(String[] args) {
ClouceBuzzService mClouceBuzzService = new ClouceBuzzService();
mClouceBuzzService.start();
}
private ServerSocket mServerSocket;
private static final int port = 5010;
private boolean flage = false;
private static List<ClientBuzz> clients = new ArrayList<ClientBuzz>();
public List<ClientBuzz> getClients() {
return clients;
}
public void removeClient(ClientBuzz item) {
if (clients.contains(item)) {
clients.remove(item);
}
}
public void run() {
try {
mServerSocket = new ServerSocket(port);
System.out.println("ServerSocket start !!!!!");
while (flage) {
try {
Socket mSocket = mServerSocket.accept();
String ip = mSocket.getInetAddress().getHostAddress();
int port = mSocket.getPort();
ClientBuzz mClientBuzz = new ClientBuzz(mSocket, this);
clients.add(mClientBuzz);
mClientBuzz.start();
System.out.println("---mServerSocket.accept() ip:" + ip
+ " port:" + port);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
if (!flage) {
flage = true;
System.out.println("service start !!!!!");
new Thread(this).start();
}
}
public void stop() {
try {
flage = false;
mServerSocket.close();
System.out.println("service stop !!!!!");
} catch (IOException e) {
e.printStackTrace();
}
}
public static class ClientBuzz implements Runnable {
private Socket mSocket;
private ClouceBuzzService mBuzzService;
private String ip;
private int port;
private OutputStream os;
private InputStream is;
private boolean flage = false;
private String device_id = null;
public ClientBuzz(Socket mSocket, ClouceBuzzService mBuzzService) {
super();
this.mSocket = mSocket;
this.mBuzzService = mBuzzService;
ip = mSocket.getInetAddress().getHostAddress();
port = mSocket.getPort();
try {
os = mSocket.getOutputStream();
is = mSocket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public void commond(String str) {
String key = getKey(str);
if (device_id != null && key != null && key.equals(device_id)) {
String value = getValue(str);
if (value.equals("on") || value.equals("off")) {
try {
os.write(("commond:" + value).getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void doMsg(String msg) {
// os.write(("deviceId:"+BUZZ_DEVICE_ID).getBytes());
if (msg != null) {
String key = getKey(msg);
if (key != null) {
if (key.equals(DEVICE_ID_STRING)) {
device_id = getValue(msg);
System.out.println("ip:" + ip + "\nport:" + port
+ "\ndevice_id:" + device_id);
} else if (msg.equals("close")) {
flage = false;
} else {
for (ClientBuzz item : mBuzzService.getClients()) {
item.commond(msg);
}
}
}
}
}
public void run() {
while (flage) {
byte[] buffer = new byte[1024 * 2];
try {
int len = is.read(buffer);
if (len <= 0) {
// 客戶端斷開
flage = false;
} else {
String str = new String(buffer, 0, len).trim();
if (str.equals("close")) {
flage = false;
} else {
doMsg(str);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
mBuzzService.removeClient(this);
}
public void start() {
flage = true;
}
public void stop() {
try {
flage = false;
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMsg(String string) {
if (os != null) {
try {
os.write(string.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

        build.sh
#!/bin/sh
if [ "$1" = "clean" ]
then
rm *.class *.jar
else
javac *.java
jar cvf buzz_icloud.jar *.class
rm *.class
java -classpath buzz_icloud.jar ClouceBuzzService
fi



開發板這端:
FS210 # set bootcmd tftp 0x40008000 uImage \; bootm 0x40008000
FS210 # set serverip 192.168.7.121
FS210 # set ethaddr 192.168.7.191
FS210 # set ethaddr 00:23:32:23:32:11
FS210 # set bootargs console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.7.121:/opt/rootfs_dir ip=192.168.7.191 init=/init
FS210 # save
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章