学习Linux下s3c2440的USB鼠标驱动笔记

发布者:Qingliu2022最新更新时间:2024-07-23 来源: cnblogs关键字:Linux  s3c2440 手机看文章 扫描二维码
随时随地手机看文章

1、ARM-Linux下USB驱动程序开发

1.1.1、linux下USB配置:

*********(MassStorage:存储设备)************************************

-> Device Drivers

-> SCSI device support(通用设备)

-> SCSI disk support (磁盘支持)

-> SCSI device support(设备支持)


-> Device Drivers

-> USB support (USB设备)

-> USB device filesystem (USB设备文件系统)

-> OHCI HCD support (主要是非PC上的USB芯片)

-> USB Mass Storage support(USB大容量设备)

-> USB Monitor (USB 主设备)


-> File systems

-> DOS/FAT/NT Filesystems

-> MSDOS fs support

-> VFAT (Windows-95) fs support


-> Partition Types (分区类型)

-> PC BIOS (MSDOS partition tables) support


-> Native Language Suppor (本地语言设置)

-> Simplified Chinese charset (CP936, GB2312)

-> NLS UTF-8


make uImage (生成uImage)

测试 mount /dev/sda1 /mnt/


*********(HID:人机接口(鼠标、键盘))********************************

-> Device Drivers

HID Devices --->

-> USB Human Interface Device (full HID) support

USB support --->

-> Support for Host-side USB

make uImage (生成uImage)

测试 cat /dev/mouse1


*********(RNDIS:网卡)********************************


-> Device Drivers x

-> USB support x

-> USB Gadget Support

Support for USB Gadgets

Ethernet Gadget (with CDC Et hernet support) x x

[*] RNDIS support (EXPERIMENTAL) (NEW)

编译内核模块


cp drivers/usb/gadget/_ether.ko /work/nfs_root/first_fs/

cp /arch/arm/boot/uImage /work/nfs_root/new_uImage


*********(CDC-ACM:USB虚拟串口)********************************

(未能识别USB driver)可能是没有配置USB设备


 



1.2.1、驱动程序编写

struct usb_driver {

const char *name; /*USB驱动名字*/

int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);/*USB core发现该驱动程序能够处理USB接口时,调用*/

void (*disconnect) (struct usb_interface *intf);/*USB移除的时候调用*/

const struct usb_device_id *id_table; /*该驱动程序支持哪些设备 idVendor(制造商ID) idProduct(产品id)*/

};

1.2.2、linux提供宏来定义 一种 设备 :

USB_DEVICE(vend,prod)

vend:USB Vendor ID 制造商ID

prod:USB Product ID 设备ID


1.2.3、linux提供宏来定义 一类 设备 :

USB_INTERFACE_INFO(cl,sc,pr)

cl:类 blnterfaceClass Value

sc:子类 blnterfaceSubClass value

pr:协议 blnterfaceProtocil Value


1.2.4、USB注册:传入一个参数usb_driver

static inline int usb_register(struct usb_driver *driver)


1.2.5、usb_device结构

int devnum; /* Address on USB bus */

char devpath [16]; /* Use in messages: /port/port/... */

enum usb_device_state state; /* configured, not attached, etc */

enum usb_device_speed speed; /* high/full/low (or error) */

struct usb_device_descriptor descriptor; /* Descriptor 设备描述符号*/

struct usb_host_config *config; /* All of the configs */

struct usb_config_descriptor desc; /*usb配置描述符*/

struct usb_interface *interface[USB_MAXINTERFACES];

ruct usb_host_interface *cur_altsetting; /* the currently

/*USB 接口描述符 一个[配置]包含一个或者多个接口,一个接口包含一个或者多个[设置] */

struct usb_interface_descriptor desc;

struct usb_host_endpoint *endpoint; /*USB端点*/

struct usb_endpoint_descriptor desc;/*USB 端点描述符 */


1.3.1、URB(usb request block)请求块 ,承载USB之间的数据传输


①URB处理流程:

1、USB设备驱动程序创建并初始化一个访问特点USB设备指定的端点的URB,并提交给USB Core

2、USB core提交该URB到USB主控制驱动程序

3、USB主控制器驱动程序根据该URB的描述信息,来访问USB设备

4、当访问设备结束后,USB主控制器驱动程序通知USB设备驱动(device)程序


②创建urb的函数为:

struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)

参数1:iso_packets:urb所含的等时数据包个数

参数2:mem_flags:内存分配标示


③初始化urb函数为:interrupt

static inline void usb_fill_int_urb (

struct urb *urb, //要初始化urb指针

struct usb_device *dev, //usb_device设备

unsigned int pipe, //要访问的端点所对应的管道,使用usb_sndintpipe()/usb_rcvintpipe()

void *transfer_buffer, //要传输数据的缓冲区

int buffer_length, //要传输数据的长度

usb_complete_t complete_fn, //当完成urb所请求的操作时候调用的回调函数

void *context, //通常取值为DEV

int interval //URB被调度的时间间隔

);

问:何为管道?

答:管道:驱动程序的数据缓冲区与一个端点的连接,代表一个在两者之间要移动数据的能力。


批量urb:使用usb_fill_bulk_urb()

控制urb: 使用usb_control_urb()

等时urb没有像中断、控制、批量传输那样有URB初始化函数,我们只有手动初始化urb.


④提交URB

在完成urb的创建和初始化后,URB就可以通过usb_smbmit_urb函数来提交给usb core

int usb_submit_urb(struct urb *urb, gfp_t mem_flags)

urb:指向URB的指针

mem_flags:内存分配标示,用于告知USB core如何分配内存换成区。



⑤URB处理 以下三种情况被认为URB处理完成,调用complete_fn函数

1、URB成功发送给设备,并且设备返回正确,URB->status = 0

2、如果接收和发送发生错误时候 urb->status = error

3、urb被取消,就发生在驱动程序通过,usb_unlink_urb() / usb_kill_urb()



鼠标驱动程序:


  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include

  8 #include

  9 #include

 10 #include

 11 #include

 12 

 13 

 14 /*创建输入设备*/

 15 static struct input_dev *uk_dev;

 16 static int len;

 17 static char *usb_buf;

 18 static dma_addr_t usb_data_dma;

 19 static struct urb *uk_urb;

 20 

 21 

 22 

 23 

 24 //usb支持的设备列表

 25 static struct usb_device_id usbmouse_key_table [] = {

 26     { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

 27         USB_INTERFACE_PROTOCOL_MOUSE) },

 28     //{USB_DEVICE(0x1234,0x5678)},

 29     { }    /* Terminating entry */

 30 };

 31 

 32 static void usb_mouse_irq(struct urb *urb)

 33 {

 34     static unsigned char pre_val;

 35 #if 0    

 36     int i;

 37     char b[100];

 38     static int cnt = 0;

 39     printk('data cnt %d: ', ++cnt);

 40     for (i = 0; i < len; i++)

 41     {

 42         printk('%02x   ', usb_buf[i]);

 43     }

 44     printk('n');

 45 

 46 

 47 

 48     /* USB鼠标数据含义

 49      * data[1]: bit0-左键, 1-按下, 0-松开

 50      *          bit1-右键, 1-按下, 0-松开

 51      *          bit2-中键, 1-按下, 0-松开 

 52      *

 53      */

 54     // if ((pre_val & (1<<0)) != (usb_buf[1] & (1<<0)))

 55     // {

 56     //     /* 左键发生了变化 */

 57     //     input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[1] & (1<<0)) ? 1 : 0);

 58     //     input_sync(uk_dev);

 59     // }

 60 

 61     // if ((pre_val & (1<<1)) != (usb_buf[1] & (1<<1)))

 62     // {

 63     //     /* 右键发生了变化 */

 64     //     input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[1] & (1<<1)) ? 1 : 0);

 65     //     input_sync(uk_dev);

 66     // }

 67 

 68     // if ((pre_val & (1<<2)) != (usb_buf[1] & (1<<2)))

 69     // {

 70     //     /* 中键发生了变化 */

 71     //     input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[1] & (1<<2)) ? 1 : 0);

 72     //     input_sync(uk_dev);

 73     // }    

 74     

 75     // pre_val = usb_buf[1];

 76     /* 重新提交urb */

 77     usb_submit_urb(uk_urb, GFP_KERNEL);

 78 

 79 #else

 80 

 81     switch (urb->status) {

 82     case 0:            /* success */

 83         break;

 84     case -ECONNRESET:    /* unlink */

 85     case -ENOENT:

 86     case -ESHUTDOWN:

 87         return;

 88     /* -EPIPE:  should clear the halt */

 89     default:        /* error */

 90         goto resubmit;

 91     }

 92 

 93     input_report_key(uk_dev, BTN_LEFT,   usb_buf[1] & 0x01);

 94     input_report_key(uk_dev, BTN_RIGHT,  usb_buf[1] & 0x02);

 95     input_report_key(uk_dev, BTN_MIDDLE, usb_buf[1] & 0x04);

 96     input_report_key(uk_dev, BTN_SIDE,   usb_buf[1] & 0x08);

 97     input_report_key(uk_dev, BTN_EXTRA,  usb_buf[1] & 0x10);

 98 

 99     input_report_rel(uk_dev, REL_X,     usb_buf[3]);

100     input_report_rel(uk_dev, REL_Y,     usb_buf[4]);

101     input_report_rel(uk_dev, REL_WHEEL, usb_buf[5]);

102 

103     input_sync(uk_dev);

104 resubmit:

105      usb_submit_urb (urb, GFP_ATOMIC);

106 #endif

107 

108 

109 

110 

111 }

112 

113 static int usbmouse_key_probe(struct usb_interface *intf, const struct usb_device_id *id)

114 {

115     struct usb_device *dev = interface_to_usbdev(intf);

116     struct usb_host_interface *interface;

117     struct usb_endpoint_descriptor *endpoint;

118     int pipe;

119     /*获取当前usb接口的设置*/

120     interface = intf->cur_altsetting;

121     endpoint  = &interface->endpoint[0].desc;

122 

123     /* a. 分配一个input_dev */

124     uk_dev = input_allocate_device();

125     /* b. 设置 */

126     /* b.1 能产生哪类事件 */

127      set_bit(EV_KEY, uk_dev->evbit);

128      set_bit(EV_REL, uk_dev->evbit);

129     

130     // /* b.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT */

131     // set_bit(BTN_LEFT, uk_dev->keybit);

132     // set_bit(BTN_RIGHT, uk_dev->keybit);

[1] [2]
关键字:Linux  s3c2440 引用地址:学习Linux下s3c2440的USB鼠标驱动笔记

上一篇:s3c2440的IIS的控制模块
下一篇:s3c2440启动代码学习笔记

推荐阅读最新更新时间:2026-02-05 13:04

基于S3C2440linux-3.6.6移植——LED驱动
目前的linux版本的许多驱动都是基于设备模型,LED也不例外。 简单地说,设备模型就是系统认为所有的设备都是挂接在总线上的,而要使设备工作,就需要相应的驱动。设备模型会产生一个虚拟的文件系统——sysfs,它给用户提供了一个从用户空间去访问内核设备的方法,它在linux里的路径是/sys。如果要写程序访问sysfs,可以像读写普通文件一样来操作/sys目录下的文件。 对于基于s3c2440的开发板来说,linux-3.6.6自动的LED驱动只需改变连接LED的IO端口,及高、低电平响应即可。我的开发板的四个LED连接在了B口的5到8引脚上,当输出低电平时被点亮,与linux自带的LED驱动一致,因此无需做任何改动。
[单片机]
郭天祥-S3C2440开发板Linux2.6.31移植教程
本人使用的开发板是广州天嵌的TQ2440开发板 最近使用了郭天祥的教程学习S3C2440嵌入式linux2.6.31系统移植,移植yaffs2文件系统成功后,发现开发板移植的系统的ping命令无法ping通电脑。后面通过烧录开发板自带的linux镜像文件和yaffs2文件系统,对比之后。发现本人的笔记本(联想G40系列),如果只接通过本地网卡与开发板直连,无法ping通,但是使用自己的台式电脑,可以使用网线直连开发板ping通,确认了问题的原因是: 1.笔记本在网线直连开发板的情况下,无法ping通开发板。 2.个人移植的linux 2.6.31操作系统驱动存在问题。 第一个问题很好解决,如果要继续
[单片机]
ARM Linux S3C2440 之时钟分析
S3c2440 时钟 & 电源管理时钟由三部分组成: Clock control ,USB control, 和 Power control Clock control 部分可以产生时钟FCLK,提供ARM内核,HCLK 提供 AHB 总线外设,还有 PLCK APB 总线外设。 s3c2440 有两个内置的PLLS 锁相环,一个提供给 FCLK,HCLK,和PCLK,另一个提供给USB时钟(48MHZ)。Clock control 可以不使用PLL,而降低的时钟,通过软件设置,时能各中种外设,从而可以降低功耗。 Power control部分,用于电能管理,有四种工作模式:Normal mode, Slow mode, Idl
[单片机]
s3c2440液晶屏驱动 (内核自带) linux-4.1.24
自带有一部分驱动的配置信息,只要修改这部分就能支援 不同的液晶屏 - /arch/arm/mach-s3c24xx/mach-smdk2440.c 另一部分在 /drivers/video/fbdev/s3c2410fb.c 先打开调试功能,这样内核在启动的时候,就可以输出这些信息,或者使用 dmesg 查看到这些信息。当然,你配置内核 make menuconfig 也可以打开,但是太麻烦了,不如这样。 1 #define CONFIG_FB_S3C2410_DEBUG 2 #define dprintk(msg...) 3 do { 4 if (debug) 5 printk(msg);
[单片机]
<font color='red'>s3c2440</font>液晶屏<font color='red'>驱动</font> (内核自带) <font color='red'>linux</font>-4.1.24
基于ARM9芯片的S3C2440Linux操作系统设计SPI驱动程序
  在嵌入式开发过程中,许多系统通常使用串口驱动来满足通信要求,但在实际应用中,使用SPI通信方式会更加高效和快捷[2]。SPI接口是一种高速、高效的串行接口技术,因而SPI设备在数据通信应用中十分方便[3]。本文基于ARM9芯片的S3C2440和Linux操作系统,设计了一种SPI驱动程序,该驱动程序功能可靠灵活、易于移植,可应用于多种嵌入式平台,实现ARM与设备之间的通信。   1 硬件说明   1.1 S3C2440开发平台   采用三星公司的SoC芯片S3C2440[4]作为核心处理器,主频为400 MHz,并与64 MB SDRAM和64 MB NAND Flash共同组成核心部分。此外,该平台也为用户提供了大量的通
[单片机]
基于ARM9芯片的<font color='red'>S3C2440</font>和<font color='red'>Linux</font>操作系统设计SPI<font color='red'>驱动</font>程序
S3C2440移植linux3.4.2内核之修改分区以及制作根文件系统
上一节S3C2440移植linux3.4.2内核之内核框架介绍及简单修改我们简单配置了内核,这节来根据继续修改内核。 启动内核 内核启动的打印信息如下图所示 可以看到内核有8个分区,而我们的uboot只有4个分区。 0x00000000-0x00040000 : bootloader //存放uboot 0x00040000-0x00060000 : params //存放环境变量 0x00060000-0x00260000 : kernel //存放内核 0x00260000-0x10000000 : rootfs //存放文件系统 所以接下来我们来修改内
[单片机]
2440串口linux编程,S3C2440串口通讯的相关配置
UART配置的相关寄存器如下(按s3c2440手册中的顺序列出): 1.ULCONn寄存器:线性控制寄存器 功能:设置奇偶校验,停止位, 数据位(5-8位) 注意:一般设置为无校验,一个停止位,数据位为8位,也就是常说的“8N1”,此时寄存器值为0x3。(bit =0为正常模式,否则为红外模式); 2.UCONn寄存器:通道n控制器 功能:选择UART时钟源、设置UART中断方式 注意:可选择PCLK、UEXTCLK或FCLK/n。bit =1为回送模式,用于测试;bit 和bit 分别控制传输和接收模式,初学者常设置为中断请求或查询模式,bit =bit =01。 3.UFCONn寄存器:FIFO控制寄存器 功能:用于设
[单片机]
嵌入式linux开发 (二十三) 内存管理(5) s3c2440内存管理
之前想着s3c2440内存管理应该和imx6ull 是一样的,目前看起来是不一样 JZ2440 S3C2440 ARM920T ARMv5t -内置 Steppingstone (4K-Byte SRAM) 无rom -外扩 EM63A165TS-6G:32MB/片,SDRAM,共两片 MX29LV160DBTI:2MB,并口 NOR FLASH K9F2G08U0C: 256MB,NAND FLASH 硬件对内存的管理 soc Supports various types of ROM for booting (NOR/NAND Flash, EEPROM, and others) N
[单片机]
嵌入式<font color='red'>linux</font>开发 (二十三) 内存管理(5) <font color='red'>s3c2440</font>内存管理
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved