用 ADB 去控制 GPIO

觉得为时已晚的时候,恰恰是最早的时候

用 ADB 操作 GPIO

转载请注明出处 https://sayid95.github.io/
背景介绍:mt8167 安卓7.0

我们经常会在底层驱动里面去操作gpio,进而去控制硬件。如果驱动层面去操作io出现问题的时候,我们不知道是不是硬件的问题,今天就来说下怎么用ADB去控制gpio。

首先

打开很难用的 Windows 的cmd.exe (推荐 一款替代品 Cmder ),adb shell连接上设备以后,输入下面的命令,

cd /sys/devices/platform/soc/1000b000.pinctrl/

进入到1000b000.pinctrl/ 的目录下,然后就可以去操作 io 口了,如下:

echo mode 66 0 > mt_gpio   /*设置66号 io 的模式*/
echo dir 66 1 > mt_gpio    /*设置66号 io 的输入,输出方向*/
echo out 66 1 > mt_gpio    /*设置66号 io 为输出*/

接着

就可以用下面的命令去看我们上面用 ADB 设置的 gpio 状态了

cat   /sys/devices/platform/soc/1000b000.pinctrl/mt_gpio

来看下mtk 这部分操作的源码

kernel-4.4/drivers/pinctrl/mediatek/pinctrl-mtk-common.c 这个文件里,下面代码就是adb 直接操作gpio的函数:

static ssize_t mt_gpio_show_pin(struct device *dev, struct device_attribute *attr, char *buf)
{
    int len = 0;
    int bufLen = PAGE_SIZE;
    struct mtk_pinctrl *pctl = dev_get_drvdata(dev);
    struct gpio_chip *chip = pctl->chip;
    unsigned        i;
    int         pull_val;

    len += snprintf(buf+len, bufLen-len,
        "PIN: [MODE] [DIR] [DOUT] [DIN] [PULL_EN] [PULL_SEL] [IES] [SMT] [DRIVE] ( [R1] [R0] )\n");

    for (i = 0; i < chip->ngpio; i++) {
        pull_val = mtk_pullsel_get(chip, i);

        len += snprintf(buf+len, bufLen-len, "%4d:% d% d% d% d% d% d% d% d% d",
                i,
                mtk_pinmux_get(chip, i),
                mtk_gpio_get_direction(chip, i),
                mtk_gpio_get_out(chip, i),
                mtk_gpio_get_in(chip, i),
                mtk_pullen_get(chip, i),
                (pull_val >= 0) ? (pull_val&1) : -1,
                mtk_ies_get(chip, i),
                mtk_smt_get(chip, i),
                mtk_driving_get(chip, i));
        if ((pull_val & 8) && (pull_val >= 0))
            len += snprintf(buf+len, bufLen-len, " %d %d", !!(pull_val&4), !!(pull_val&2));
        len += snprintf(buf+len, bufLen-len, "\n");
    }
    return len;
}

static ssize_t mt_gpio_store_pin(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int pin, val;
    int val_set;
    struct mtk_pinctrl *pctl = dev_get_drvdata(dev);
    struct pinctrl_dev *pctldev = pctl->pctl_dev;

    if (!strncmp(buf, "mode", 4) && (sscanf(buf+4, "%d %d", &pin, &val) == 2)) {
        val_set = mtk_pmx_set_mode(pctldev, pin, val);
    } else if (!strncmp(buf, "dir", 3) && (sscanf(buf+3, "%d %d", &pin, &val) == 2)) {
        val_set  = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, !val);
    } else if (!strncmp(buf, "out", 3) && (sscanf(buf+3, "%d %d", &pin, &val) == 2)) {
        mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
        mtk_gpio_set(pctl->chip, pin, val);
    } else if (!strncmp(buf, "pullen", 6) && (sscanf(buf+6, "%d %d", &pin, &val) == 2)) {
        val_set = mtk_pconf_set_pull_select(pctl, pin, !!val,
            false, MTK_PUPD_SET_R1R0_00 + val);
    } else if (!strncmp(buf, "pullsel", 7) && (sscanf(buf+7, "%d %d", &pin, &val) == 2)) {
        val_set = mtk_pconf_set_pull_select(pctl, pin, true, !!val, MTK_PUPD_SET_R1R0_01);
    } else if (!strncmp(buf, "ies", 3) && (sscanf(buf+3, "%d %d", &pin, &val) == 2)) {
        val_set = mtk_pconf_set_ies_smt(pctl, pin, val, PIN_CONFIG_INPUT_ENABLE);
    } else if (!strncmp(buf, "smt", 3) && (sscanf(buf+3, "%d %d", &pin, &val) == 2)) {
        val_set = mtk_pconf_set_ies_smt(pctl, pin, val, PIN_CONFIG_INPUT_SCHMITT_ENABLE);
    }

    return count;
}

static DEVICE_ATTR(mt_gpio, 0664, mt_gpio_show_pin, mt_gpio_store_pin);

static struct device_attribute *gpio_attr_list[] = {
    &dev_attr_mt_gpio,
};

static int mt_gpio_create_attr(struct device *dev)
{
    int idx, err = 0;
    int num = (int)(ARRAY_SIZE(gpio_attr_list));

    if (!dev)
        return -EINVAL;

    for (idx = 0; idx < num; idx++) {
        err = device_create_file(dev, gpio_attr_list[idx]);
        if (err)
            break;
    }

    return err;
}

看到源码 static DEVICE_ATTR(mt_gpio, 0664, mt_gpio_show_pin, mt_gpio_store_pin);,我们就知道其实就是利用 device_create_file 函数可以在 /sys/ 下创建对应的属性文件,从而通过对该文件的读写实现特定的数据操作。

可能不同的内核对应的节点不一样,这个例子是在 Linux 4.4下进行的,现在就去试试吧!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容