📄 drv_usb_ctl.c
字号:
sizeof (USB_STRING_LANG_ID_DESCRIPTOR); // code_transmit((D_UINT8 *)&(usb_descr.LangIDDescr), ControlData.DeviceRequest.wLength); } // 主机要求获取接口描述符 } else if (bDescriptor == USB_INTERFACE_DESCRIPTOR_TYPE) { if (ControlData.DeviceRequest.wLength > sizeof (USB_INTERFACE_DESCRIPTOR)) ControlData.DeviceRequest.wLength = sizeof (USB_INTERFACE_DESCRIPTOR); // code_transmit((D_UINT8 *)&(usb_descr.InterfaceDescr), ControlData.DeviceRequest.wLength); //}else if (bDescriptor == USB_ENDPOINT_DESCRIPTOR_TYPE) { // code_transmit((D_UINT8 *)&DeviceDescr, sizeof(USB_DEVICE_DESCRIPTOR)); } else stall_ep0 (); //没有该请求,返回STALL USB_SetEndpointReady (0, 1);}/**************************************** ** 函数名称: void set_descriptor(void) ** 功能描述: 设置描述符 *****************************************/voidset_descriptor (void){ USB_SetEndpointReady (0, 1);}/**************************************** ** 函数名称: void get_configuration(void) ** 功能描述: 获取配置 *****************************************/voidget_configuration (void){ D_UINT8 c = bEPPflags.bits.configuration; //取出配置值 single_transmit (&c, 1); //发送配置值 USB_SetEndpointReady (0, 1);}/**************************************** ** 函数名称: void set_configuration(void) ** 功能描述: 设置配置 *****************************************/// 如果设备没有收到此命令,会使用其默认的配置1voidset_configuration (void){ frm_printf("set_configuration"); if (ControlData.DeviceRequest.wValue == 0) { //配置值不对,设备进入未配置状态 DISABLE (); bEPPflags.bits.configuration = 0; //标记未配置 ENABLE (); init_unconfig (); //进入地址状态,禁止0除外的所有端点 } else if (ControlData.DeviceRequest.wValue == 1) { //配置设备 init_unconfig (); //进入地址状态,禁止0除外的所有端点 init_config (); //配置处理,允许端点收发 DISABLE (); bEPPflags.bits.configuration = 1; //标志已配置 ENABLE (); } else stall_ep0 (); //没有该请求,返回STALL USB_SetEndpointReady (0, 1);}/**************************************** ** 函数名称: void get_interface(void) ** 功能描述: 获取接口信息 *****************************************/voidget_interface (void){ D_UINT8 txdat = 0; //本设备只有一个接口 single_transmit (&txdat, 1); //发送一个字节 USB_SetEndpointReady (0, 1);}/**************************************** ** 函数名称: void set_interface(void) ** 功能描述: 设置接口信息 *****************************************/voidset_interface (void){ USB_SetEndpointReady (0, 1);} voidsynch_frame (void){ D_UINT8 frame_number[2]; frame_number[0] = 0x33; frame_number[1] = 0x3; code_transmit (frame_number, 2); USB_SetEndpointReady (0, 1);} voidget_max_lun (void){ D_UINT8 c; c = 0; code_transmit (&c, 1);}/************************************************************* ** 函数名称: void control_handler(void) ** 功能描述: 控制传输(执行控制命令 -- 13中控制命令) **************************************************************/voidcontrol_handler (void){ D_UINT8 type, req; type = ControlData.DeviceRequest.bmRequestType & USB_REQUEST_TYPE_MASK; //读取请求代码 req = ControlData.DeviceRequest.bRequest & USB_REQUEST_MASK;printf("req=%d\n",req); if (type == USB_STANDARD_REQUEST) (*StandardDeviceRequest[req]) (); //标准请求处理 //else if (type == USB_VENDOR_REQUEST) //厂商请求 // (*VendorDeviceRequest[req])(); else if (type == USB_CLASS_REQUEST) (*ClassDeviceRequest[req]) (); //类请求,如大容量类 else stall_ep0 (); //无效请求,返回STALL }// 读取主机发来的命令, 并根据命令执行相应动作voidep0_setupdone (void){ D_UINT8 req[sizeof (DEVICE_REQUEST)]; ControlData.wLength = 0; //传输字节总数清0 ControlData.wCount = 0; //传输字节计数器清0 // 读取主机发来的命令及其参数,并保存到req中 /* if (USB_ReadEndpoint (0, sizeof (ControlData.DeviceRequest), req) != sizeof (DEVICE_REQUEST)) { //从端点0读8个字节失败 USB_SetEndpointStall (0, 1); //停止控制端点0 //USB_SetEndpointStall(1, 1); //停止控制端点1 bEPPflags.bits.control_state = USB_IDLE; //设置为等待状态 return; }*/ /******* 以下语句通信中的解决大小端问题,使该函数与编译器无关 ****/ // 将读取的命令及其参数赋值到ControlData中 memcpy(req,rx_data,8); free(rx_data); int i; for(i=0;i<8;i++) printf("%d\n",req[i]); ControlData.DeviceRequest.bmRequestType = req[0]; ControlData.DeviceRequest.bRequest = req[1]; ControlData.DeviceRequest.wValue = (req[3] << 8) | req[2]; ControlData.DeviceRequest.wIndex = (req[5] << 8) | req[4]; ControlData.DeviceRequest.wLength = (req[7] << 8) | req[6]; /******** 接收建立包成功 **********/ //USB_AcknowledgeEndpoint(0); //对控制端点0进行建立包应答 //USB_AcknowledgeEndpoint(1); //对控制端点1进行建立包应答 ControlData.wLength = ControlData.DeviceRequest.wLength; //取出要传输数据的总字节数 // 查看紧跟该命令之后的数据的传输方向 // 如果数据的传输方向是: 设备至主机(直接执行命令,并将主机需要的数据写入FIFO中) if (ControlData.DeviceRequest. bmRequestType & (D_UINT8) USB_ENDPOINT_DIRECTION_MASK) { printf("ep0 in\n"); //如果控制传输是控制读取 //bEPPflags.bits.setup_packet = 1; //通知control_handler()处理Setup包 bEPPflags.bits.control_state = USB_TRANSMIT; //设置为发送状态 control_handler (); //调用请求处理子程序 } // 如果数据的传输方向是: 主机至设备 else { //控制传输是控制写入 // 如果该命令没有后续数据 printf("ep0 out\n"); if (ControlData.DeviceRequest.wLength == 0) { // bEPPflags.bits.setup_packet = 1; //通知control_handler()处理Setup包 bEPPflags.bits.control_state = USB_IDLE; //设置为等待状态 // SET_ADDRESS命令需要等到IN包到来时才能执行,这里只是标识有该命令需要执行 if (ControlData.DeviceRequest.bRequest == USB_REQUEST_SET_ADDRESS) { bEPPflags.bits.command = CMD_SET_ADDRESS; USB_SetEndpointReady (0, 1); } else control_handler (); //调用命令处理子程序 } else { // 数据长度出错 if (ControlData.DeviceRequest.wLength > MAX_CONTROLDATA_SIZE) { bEPPflags.bits.control_state = USB_IDLE; //设置为等待状态 USB_SetEndpointStall (0, 1); //停止控制端点0 } // udc准备接收数据 else { bEPPflags.bits.control_state = USB_RECEIVE; //设置为接收状态 USB_SetEndpointReady (0, 1); } } // set command with data } // else set command USB_SetEndpointReady(0,1);}/*************************************** ** 函数名称: void ep0_rxdone(void) ** 功能描述: 通过端点索引 0 接收数据 ** 输 入: 无 ** 输 出: 无 ***************************************/// EP0收到OUT包后的处理函数;接收HOST发来的数据// 如果EP0收到的是命令有后续的数据输出,则调用该函数,负责接收后续的输出数据voidep0_outdone (void){ D_INT16 i; /***** 下面为控制写入的数据阶段 ***************/ if (bEPPflags.bits.control_state == USB_RECEIVE) { //如果为接收状态 //从端点0接收数据(收到的数据作何处理? ) i = USB_ReadEndpoint (0, MAX_CONTROLDATA_SIZE, ControlData.dataBuffer + ControlData.wCount); ControlData.wCount += i; //统计已接收的字节数 //数据接收完毕 if (i != MAX_CONTROLDATA_SIZE || ControlData.wCount >= ControlData.wLength) { //bEPPflags.bits.setup_packet = 1; //通知control_handler()处理Setup包 bEPPflags.bits.control_state = USB_IDLE; //设置为等待状态 control_handler(); //调用请求处理子程序 return; } } else bEPPflags.bits.control_state = USB_IDLE; //设置等待状态 USB_SetEndpointReady (0, 1);}/*************************************** ** 函数名称: void ep0_txdone(void) ** 功能描述: 通过端点索引 0 发送数据 ** 输 入: 无 ** 输 出: 无 ***************************************/// EP0收到IN包,UDC发送数据到HOSTvoidep0_indone (void){ D_INT16 i = ControlData.wLength - ControlData.wCount; //计算未发送的字节数 //USB_ReadLastTransactionStatus(1); //清除中断寄存器标志位 // SET_ADDRESS命令将在数据阶段得到执行(无可发送数据) if (bEPPflags.bits.control_state != USB_TRANSMIT) { //非发送状态 //single_transmit(0, 0); if (bEPPflags.bits.command == CMD_SET_ADDRESS) { bEPPflags.bits.command = CMD_IDLE; control_handler (); } else USB_SetEndpointReady (0, 1); return; //返回 } if (i >= EP0_PACKET_SIZE) { //未发送字节数大于16,发送16个字节 USB_WriteEndpoint (0, EP0_PACKET_SIZE, ControlData.pData + ControlData.wCount); ControlData.wCount += EP0_PACKET_SIZE; bEPPflags.bits.control_state = USB_TRANSMIT; } else if (i != 0) { //发送所有未发送的字节 USB_WriteEndpoint (0, i, ControlData.pData + ControlData.wCount); ControlData.wCount += i; bEPPflags.bits.control_state = USB_IDLE; //置状态为等待状态 } else if (i == 0) { USB_WriteEndpoint (0, 0, 0); //发送完毕,发0个字节 bEPPflags.bits.control_state = USB_IDLE; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -