首页 > 系统相关 >Linux 2.4G USB遥控板驱动

Linux 2.4G USB遥控板驱动

时间:2023-03-23 16:46:39浏览次数:35  
标签:USB urb struct usbKey KEY Linux usb input 2.4

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/usb.h>
#include <media/rc-core.h>

static struct rc_map_table usbKey_map[] = {
  { 0x4F, KEY_RIGHT }, { 0x50, KEY_LEFT },
  { 0x51, KEY_DOWN }, { 0x52, KEY_UP },
  { 0x28, KEY_ENTER }, { 0x65, KEY_TAB},
  { 0x29, KEY_ESC }, { 0x2A, KEY_MENU },
  { 0x1E, KEY_1 }, { 0x1F, KEY_2 },
  { 0x20, KEY_3 }, { 0x21, KEY_4 },
  { 0x22, KEY_5 }, { 0x23, KEY_6 },
  { 0x24, KEY_7 }, { 0x25, KEY_8 },
  { 0x26, KEY_9 }, { 0x27, KEY_0 },
  { 0x4E, KEY_PREVIOUS }, { 0x4B, KEY_NEXT },
};

struct usbKey_st
{
  struct input_dev *input;

  size_t buffLenth; //缓存长度
  char *usbKey_vaddr; //虚拟地址
  dma_addr_t usbKey_phyc; //物理地址
  struct urb *usbKey_urb; //usb urb
};
static struct usbKey_st usbKey;

static void usbKey_complete(struct urb *urb)
{
  int ret =0;
  int i=0;

  //判断urb是否正确接收数据
  switch(urb->status)
  {
    case 0:
      break;
    case -ECONNRESET: /* unlink */
    case -ENOENT:
    case -ESHUTDOWN:
      return;
    default: /* error */
      goto resubmit;
  }

  for(i=0 ;i<20 ;i++)
  {
    if(usbKey.usbKey_vaddr[2] == usbKey_map[i].scancode)
    {
      input_report_key(usbKey.input, usbKey_map[i].keycode, 1);
      input_sync(usbKey.input);
      input_report_key(usbKey.input, usbKey_map[i].keycode, 0);
      input_sync(usbKey.input);

      break;
    }
  }

  resubmit:
    ret = usb_submit_urb(urb, GFP_ATOMIC);
    if(ret) printk("usbKey receve error\r\n");
}

static int usbKey_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
  struct usb_device *dev = interface_to_usbdev(intf);
  struct usb_endpoint_descriptor *endpoint;
  struct usb_host_interface *interface;
  int pipe;
  int ret =0,i=0;

  //获取当前接口
  interface=intf->cur_altsetting;

  //当前接口下的端点描述符
  endpoint = &interface->endpoint[0].desc;

  //其中一个中断端点
  if(endpoint->wMaxPacketSize ==8)
  {
    /************************input*****************************/
    //申请input设备
    usbKey.input = input_allocate_device();
    if(usbKey.input ==NULL)
    {
      printk("input_allocate_device error\r\n");
      ret = -ENOMEM;
      goto input_allocate_err;
    }

    //设置input上报事件
    __set_bit(EV_KEY, usbKey.input->evbit); //按键事件
    for(i=0;i<20;i++)
    {
      __set_bit(usbKey_map[i].keycode ,usbKey.input->keybit); //按键值
    }

    //注册input设备
    ret = input_register_device(usbKey.input);
    if(ret)
    {
      printk("input_register_device error\r\n");
      ret = -ENOMEM;
      goto input_register_err;
    }

    /************************USB*****************************/
    //创建一个端点管道
    pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

    //获取每包最大长度
    usbKey.buffLenth = endpoint->wMaxPacketSize;

    //申请内存
    usbKey.usbKey_vaddr = usb_alloc_coherent(dev, usbKey.buffLenth, GFP_ATOMIC, &usbKey.usbKey_phyc);
    if(usbKey.usbKey_vaddr ==NULL)
    {
      printk("usb_alloc_coherent error\r\n");
      ret = -ENOMEM;
      goto coherent_err;
    }

    //创建usb urb
    usbKey.usbKey_urb = usb_alloc_urb(0, GFP_KERNEL);
    if(usbKey.usbKey_urb ==NULL)
    {
      printk("usb_alloc_urb error\r\n");
      ret = -ENOMEM;
      goto alloc_urb_err;
    }

    //初始化urb
    usb_fill_int_urb(
      usbKey.usbKey_urb,
      dev,
      pipe,
      usbKey.usbKey_vaddr,
      usbKey.buffLenth,
      usbKey_complete,
      0,
      endpoint->bInterval
    );

    //urb DMA 设置
    usbKey.usbKey_urb->transfer_dma = usbKey.usbKey_phyc;
    usbKey.usbKey_urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;

    //urb上报数据
    ret = usb_submit_urb(usbKey.usbKey_urb, GFP_ATOMIC);
    if(ret)
    {
      printk("usb_submit_urb error\r\n");
      ret = -ENOMEM;
      goto submit_urb_err;
    }

    printk("usbKey_probe sucess\r\n");
  }

  //另一个中断端点
  if(endpoint->wMaxPacketSize ==7)
  {
  }

  return 0;

submit_urb_err:
  usb_free_urb(usbKey.usbKey_urb);
alloc_urb_err:
  usb_free_coherent(dev, usbKey.buffLenth, usbKey.usbKey_vaddr, usbKey.usbKey_phyc);
coherent_err:
  input_unregister_device(usbKey.input);
input_register_err:
  input_free_device(usbKey.input);
input_allocate_err:
  return ret;
}

static void usbKey_disconnect(struct usb_interface *intf)
{
  struct usb_device *dev = interface_to_usbdev(intf);
  struct usb_endpoint_descriptor *endpoint;
  struct usb_host_interface *interface;

  //获取当前接口
  interface=intf->cur_altsetting;

  //当前接口下的端点描述符
  endpoint = &interface->endpoint[0].desc;

  //usb卸载
  if(endpoint->wMaxPacketSize ==8)
  {
    /************************USB*****************************/
    usb_kill_urb(usbKey.usbKey_urb);
    usb_free_urb(usbKey.usbKey_urb);
    usb_free_coherent(dev, usbKey.buffLenth, usbKey.usbKey_vaddr, usbKey.usbKey_phyc);

    /************************input*****************************/
    //卸载输入设备
    input_unregister_device(usbKey.input);
    input_free_device(usbKey.input);

    printk("usbKey_disconnect sucess\r\n");
  }

  if(endpoint->wMaxPacketSize ==7)
  {
  }
}

const struct usb_device_id usbKey_id[] =
{
  {USB_DEVICE(0x276d,0x1101)},
  {},
};

static struct usb_driver usbKey_dev =
{
  .name = "usbKey",
  .probe = usbKey_probe,
  .disconnect = usbKey_disconnect,
  .id_table = usbKey_id,
};

static int __init usbKey_init(void)
{
  return usb_register(&usbKey_dev);
}

static void __exit usbKey_exit(void)
{
  usb_deregister(&usbKey_dev);
}

module_init(usbKey_init);
module_exit(usbKey_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jtb");  

 

标签:USB,urb,struct,usbKey,KEY,Linux,usb,input,2.4
From: https://www.cnblogs.com/linux-learn/p/17247992.html

相关文章

  • Linux端口转发的几种常用方法
    在一些实际的场景里,我们需要通过利用一些端口转发工具,比如系统自带的命令行工具或第三方小软件,来绕过网络访问限制触及目标系统。本文总结了Linux端口转发的一些常用方法,欢......
  • Linux系统的六大特点,你知道几个?
    提到操作系统,大家肯定都知道Windows,其实Linux也是一个操作系统,与Windows不同的是,Linux是一套开放源代码程序的、可以自由传播的类Unix操作系统软件。以下是详细的内容:......
  • Oracle VM VirtualBox+vagrant搭建Linux虚拟机
    OracleVMVirtualBox+vagrant,搭建Linux虚拟机title:OracleVMVirtualBox+vagrant,搭建Linux虚拟机tags:-vm-vagrant-VirtualBoxcategories:-学习语录Ora......
  • Linux中给添加用户并创建该用户权限的文件夹
    在公司开发过程中经常会遇到在同一台编译机上给不同的用户创建权限等需求,在这里贴上相应的代码添加用户useradd-musername-ppassword-d/data/home/gengkaiyuuse......
  • linux系统内存溢出Out of memory
    有一台服务器的内存是32g,我在上面跑了一个mysql数据库,后面经常发现mysql隔三差五的就down了,通过查看系统日志发现操作系统OOM了grep"Outofmemory"/var/log/messages......
  • linux基本操作
    删除相同的行并且显示相同行出现的次数uniq-c排序sort:-n以数值排序防止出现1<10这种按字符比较的情况-t指定排序的分隔符-k指定按照第几列进行排序......
  • Linux 网络配置 ---桥接模式---最简单的方法!!!
    1.桥接模式(Bridged)VMware桥接模式,也就是将虚拟机的虚拟网络适配器与主机的物理网络适配器进行交接,虚拟机中的虚拟网络适配器可通过主机中的物理网络适配器直接访问到外部......
  • centos7 Linux 安装及升级node、npm
    centos7初始版本node6npm3 更新升级node版本#安装nnpminstall-gn#查看版本n--version//v9.0.1#把当前系统的Node更新成最新的“稳定版本”nstabl......
  • linux静默安装oracle11g 执行dbca.rsp时出错
    问题大概是:[oracle@bogon~]$$ORACLE_HOME/bin/dbca-silent-responseFile/home/oracle/etc/dbca.rspExceptioninthread"main"java.lang.NullPointerExceptionato......
  • windows和linux文件格式互转
     #查看当前文件格式cat-Afilename每行结尾是^M$为windows每行结尾是$为linux方式一:dos2unixtest2.txt#把DOS格式的文本文件转变成UNIX下的文本文件方......