用户登录
用户注册

分享至

word0x80000000 SMPP协议java如何写

  • 作者: 嗫?暁雲?
  • 来源: 51数据库
  • 2020-04-16

SMPP协议

3.1SMPP规范简介

SMPP接口协议最初由ETSI收录在 GSM03.39规范中,描述了短消息中心与短消息实体之间通信交互的协议关系及数据传输格式,本规范对SMPP接口协议的描述主要面向简单的通信交互,制定规范的厂家将其协议版本号定为V3.30;后由SMPP开发者论坛将协议版本向前演进为V3.40,SMPP V3.40协议规范完全兼容GSM 03.39协议标准。本规范中,所采用的短消息中心设备与短消息股票交易业务处理平台之间的接口采用GSM03.39 V3.30协议规范,如无特殊说明全部以此协议规范为准。SMPP协议可以以TCP/IP或X.25作为底层通讯承载。

与SMPP协议规范相关的参考资料如下:

1、 《GSM 03.39(Version 5.0.0)》:European digital cellular telecommunications system(Phase 2);Interface protocols for the connection of Short Message Service Centres(SMSCs)to Short Message Entities(SMEs);

2、 《GSM 03.39(Version 6.0.0)》:European digital cellular telecommunications system(Phase 2+);Interface protocols for the connection of Short Message Service Centres(SMSCs)to Short Message Entities(SMEs);

3、 《GSM 03.40(Version 4.8.1):European digital cellular telecommunications system(Phase 2);Technical realization of the Short Message Service Point to Point》

4、 《GSM 03.38(Version 5.2.0):Digital cellular telecommunications system(Phase 2+);Alphabets and language_specific information》

5、 《GSM 03.47(Version 5.0.0):Digital cellular telecommunications system;Example protocol stacks for interconnecting Service Center(SC) and Mobile_services Switching Center(s)(MSC)》

6、 《900/1800 MHz 数字蜂窝移动通信系统短消息中心设备规范(第一分册点对点短消息业务)》

缩略语

SME 短消息实体

SMPP 短消息点对点协议

SMSC 短消息服务中心

ESME 扩展短消息实体

3.2 系统结构、功能概述

通过SMPP,ESME(例如寻呼台、语音邮箱系统、股票交易业务处理平台等)能连接(Bind)或断连(UnBind)短消息中心,提交(Submit)短消息或从短消息中心下发(Deliver)。

此协议包含以下两部分:

*(协议)ESME到SMSC的消息

*(协议)SMSC到扩展ESME的消息

其中用户管理部分只适用于SMSC有用户数据库支持的情况

SMSC和ESME之间的关系如下图所示:

图3-1:SMSC和ESME连接的短消息系统网络

3.3 消息协议

按短消息信息的流向,可以将ESME与SMSC之间的短消息信息分为两类:1、从SMSC到ESME的消息;2、从ESME到SMSC的消息。对于所有请求消息,无论始发于ESME还是SMSC,都必须产生一个响应消息(acknowledge)。

从ESME到SMSC所提交的消息,可能有两种响应:

*SMSC收到消息的响应(ACK)

*如果这条短消息设置了需要状态报告,那么当这条短消息到达目标地之后,SMSC会产生一个状态报告的消息给ESME。

.1 SMSC到ESME的消息

以下消息是从SMSC到ESME的消息

命令

描述

bind_receiver_resp

bind_receiver的响应,status表示连接成功与否

bind_transmitter_resp

bind_transmitter的响应,status表示连接成功与否

unbind_resp

unbind的响应,status表示断开连接成功与否

submit_sm_resp

submit_sm的响应,status表明提交短消息是否成功

deliver_sm

SMSC下发短消息到ESME

enquire_link_resp

Enquire_link的响应

generic_nak

表示消息头有错误的响应

.2 ESME到SMSC的消息

以下为ESME到SMSC的消息

命令

描述

bind_receiver

短消息实体(ESME/SME)作为服务器与短消息中心(SMSC)建立连接,本连接建立起来后,允许短消息实体接受短消息中心下发的短消。

bind_transmitter

短消息实体(ESME/SME)作为客户端与短消息中心(SMSC)建立连接,本连接建立起来后,允许短消息实体向短消息中心提交短消息。

Unbind

短消息实体(ESME/SME)与短消息中心系统(SMSC)断开会话连接。

submit_sm

ESME提交短消息到SMSC,以便SMSC下发此短消息到指定的移动台。

deliver_sm_resp

deliver_sm的响应。status表示此次下发是否成功。

Enquire_link

短消息实体向短消息中心发起的连路保持查询请求,以保证通讯链路的畅通。一般情况下约每5秒发送一次ENQUIRE_LINK消息。

Generic_nak

表示消息头有错误的响应

3.4消息语法

3.4.1语法定义规则

在以下语法说明中,遵从以下规则:

A.未使用的字段,依据类型必须设置为0或NULL。

B.消息由消息头和消息体组成

C.状态(status)如在命令语法中未加说明

0:表示成功

非0:表示失败

<0x80000000:未定义值保留

D.在类型中,可能用到以下定义

l integer :一定字节数所组成的整数,高位在前,低位在后。例如:1字节(BYTE),2字节(WORD ) , 4字节(DWORD)。

l C_String :以NULL结束的ASCII字符串

l C_DecString :以NULL结束的ASCII字符串,它由一系列的10进制字符组成(‘0’---‘9’)。

l C_OctetString :由任意8位字节组成数据流串。

l C_HexString :以NULL结束的ASCII字符串,它由一系列的16进制字符组成(‘0’---‘9’,‘A’(‘a’)---‘F’(‘f’))

l C_StringTime :表示时间的字符串,它为以下格式 “YYMMDDhhmmsstnnp" ,格式如下

说明

YY'

年份的最后2位 (00-99)

MM

月份(01-12)

DD

日 (01-31)

Hh

小时 (00-23)

Mm

分 (00-59)

Ss

秒 (00-59)

T

十分之一秒 (0-9)

Nn

与UTC (Universal Time Constant) 时间超前或落后的差距(00-48).

‘+’(p)

时间超前于UTC time.

‘-’(p)

时间落后于 UTC time.

l C_UnicodeString :Unicode编码的字符串。

3.4.2消息头语法

字段

长度(字节)

类型

Command Length

4

Integer

Command ID

4

Integer

Command_status

4

Integer

Sequence No.

4

Integer

Optional Message Body

可变

混合

具体字段描述说明:

l Command Length:整个包的长度(包括该字段本身)。

l Command ID :这个字段表明该条短消息的类型,相当于标识符。例如ESME_SUB_SM表示此消息为ESME向SMSC提交短消息。当该标识符表示该条消息是请求消息(request)时,标识符的保留取值范围是0h到FFh。当该标识符表示该条消息是应答消息(response)时,标识符的保留取值范围是080000000h到0800000FFh。一般来说,应答消息的类型对应相应的请求消息的类型,所不同的是,应答消息的类型在第31位比特处是置位的。

Command ID命令取值:

Command ID 编码

Command ID

描述

Command ID取值

ESME_BNDRCV

bind_receiver

ESME要求以接收者身份连接到SMSC

0X00000001

ESME_BNDRCV_RESP

bind_receiver_resp

bind_receiver的响应

0X80000001

ESME_BNDTRN

bind_transmitter

ESME要求以发送者身份连接到SMSC

0X00000002

ESME_BNDTRN_RESP

bind_transmitrer_resp

bind_transmitter的响应

0X80000002

ESME_UBD

Unbind

ESME要求断开连接到SMSC

0X00000006

ESME_UBD_RESP

Unbind_resp

Unbind的响应

0X80000006

ESME_SUB_SM

Submit_sm

ESME提交短消息到SMSC

0X00000004

ESME_SUB_SM_RESP

Submit_sm_resp

submit_sm的响应

0X80000004

SMSC_DELIVER_SM

Deliver_sm

SMSC下发短消息到ESME

0X00000005

SMSC_DELIVER_SM_RESP

Deliver_sm_resp

deliver_sm的响应

0X80000005

ESME_QRYLINK

Enquire_link

ESME询问与SMSC的连接情况

0X00000015

ESME_QRYLINK_RESP

Enquire_link_resp

enquire_link的响应

0X80000015

ESME_NACK

Nack

表示消息头有错误的响应

0X80000000

l Command Status :此字段表示一个请求消息的成功与失败,如失败,指示引起失败的错误类型等信息。该字段只用在应答消息中,在请求消息中,该字段必须为NULL。

Command Status取值说明 :

错误代码

错误值

描述

E_SUCCESS

0X00000000

成功

E_OTHERERR

0X00000001

其他错误

0X00000002 – 0X0000000F

保留给SMSC厂商定义错误

E_MSGLENERR

0X00000010

消息长度错误

E_CMDLENERR

0X00000011

命令长度错误

E_INVLDCMDID

0X00000012

消息ID无效

E_NORIGHT(0X00000013)

0X00000013

没有执行此命令的权限

0X00000014 – 0X0000001F

保留

E_INVLDSYSTEMID

0X00000020

无效的SYSTEMID

E_INVLDPASSWORD

0X00000021

无效的密码

E_INVLDSYSTEMTYPE

0X00000022

无效的SYSTEMTYPE

0X00000023 – 0X0000003F

保留

E_ADDRERR

0X00000040

地址错误

E_MOEXCEED

0X00000041

超过最大提交数

E_MTEXCEED

0X00000042

超过最大下发数

E_INVLDUSER

0X00000043

无效的用户

E_INVLDDATAFMT

0X00000044

无效的数据格式

E_CREATEMSGFAILURE

0X00000045

创建消息失败

E_INVLDMSGID

0X00000046

无效的短消息ID

E_DATABASEFAILURE

0X00000047

数据库失败

E_CANCELMSGFAILURE

0X00000048

取消消息失败

E_MSGSTATEERR

0X00000049

短消息状态错误

E_REPLACEMSGFAILURE

0X0000004A

替换消息失败

E_INVLDRPLADDR

0X0000004B

替换消息源地址错误

0X0000004C – 0X0000005F

保留

E_INVLDORGTON

0X00000060

无效的源地址TON

E_INVLDORGNPI

0X00000061

无效的源地址NPI

E_ORGADDRERR

0X00000062

源地址错误

E_INVLDDESTTON

0X00000063

无效的目的地址TON

E_INVLDDESTNPI

0X00000064

无效的目的地址NPI

E_DESTADDRERR

0X00000065

目的地址错误

E_INVLDSCHEDULE

0X00000066

无效的定时时间

E_INVLDEXPIRE

0X00000067

无效的超时时间

E_INVLDESM

0X00000068

无效的ESM_CALSS

E_INVLDUDLEN

0X00000069

无效的UDLEN

E_INVLDPRI

0X0000006A

无效的PRI

E_INVLDRDF

0X0000006B

无效的Registered_delivery_flag

E_INVLDRPF

0X0000006C

无效的Replace_if_present_flag

0X0000006D – 0X0000007F

保留

用户管理部分(可选)

E_USERALREADYEXIST

0X00000080

指定用户已经存在

E_CREATEUSERERR

0X00000081

创建用户失败

E_USERIDERR

0X00000082

用户ID错误

E_USERNOTEXIST

0X00000083

指定用户不存在

0X00000084 – 0X0000008F

保留

0X00000090 – 0X00000FFF

保留给SMSC厂商定义错误

其他

保留

l Sequence No .:此字段表示消息的序列号,它由ESME产生,它是消息和它的应答之间的对应标志,数值在01h到07FFFFFFFh间。对于每条请求消息,该字段的取值必须保证严格单调递增,当序列号值达到最大值时,返回继续从01h开始。

l Optional Message Body:此字段表示短消息的消息体部分,在移动股票交易应用中承载STK卡应用协议内容。

3.4.3各命令消息体具体格式

1、generic_Nak命令

此命令用于当接收消息头有错误的时候的响应,该响应只能由收到请求方发出。该命令只有消息头,没有消息体。

2、BIND_RECEIVER命令

在扩展短消息实体和短消息中心之间建立虚连接,接收SMSC转发的短消息。

字段

长度(字节)

类型

System_id

最大 16

C_String

Password

最大 9

C_String

System_type

最大 13

C_String

Interface_version

1

Integer

Addr_ton

1

Integer

Addr_npi

1

Integer

Address_range

最大 41

C_DecString

具体字段描述说明:

system_id :该字段是系统登录到短消息中心所用的接口号。

Password :该字段是系统登录到短消息中心所用的密码。

system_type :该字段标明登录的接口类型。

interface_version :该字段标明登录的接口版本号。

addr_ton :该字段指明编码类型。如不需要,可设为NULL。取值说明:

0 未知,当用户或网络不含关于编码方案的较早信息

1 国际号码,

2 国内号码

3 网络特殊号码

4 用户号码

5 字符数字

6 缩写号码

7 保留

addr_npi :该字段指明编码方案。如不需要,可设为NULL。取值说明:

0 未知

1   ISDN或电话号码编码方案(E164/E163),对于任意实体SC,MSC或MS,都有效

2 保留

3 数据编码方案(X121)

4 电报编码方案

5-7 保留

8 国内编码方案

9 私有编码方案

10 ERMES编码方案(ETSI DE/PS 3 01-3)

11-15 保留

address_range :该字段用来给短消息指明路由,和将状态报告转发给ESME。如不需要,可设置为NULL。

3、BIND_RECEIVER_RESP语法

此命令用于对MI_BIND_RECEIVER响应。

字段

大小(字节)

类型

System_id

最大 16

C_String

有没有6747的bootloader例程啊

我这里简单的说一下:上电复位开始运行内部固化的BootLoader(RBL),它的位置是在0x1170_0000,RBL根据Boot引脚的状态从相应的Flash中将我们的程序拷贝到内部或外部RAM,然后将DSP的控制权交给应用程序!!AISgen D800K003是一个把CCS编译生成的out文件转换成下载要的bin文件,下面给一个bin 例子(为方便以字组织):0x41504954//magic word 每一个由Aisgen生成的bin都是以这个字开头的0x5853590D////根据我们在D800K003中勾选的情况调用0x000200000x180102020x000501B9………… 0x5853590D//调用RBL内部初始化函数 LPS Setting PSC0,如果我们在D800K003中没有勾选Configure LPS,0x00010006//Bin文件中就不会有这个调用0x000000030x5853590D0x000100060x00010003…………0x5853590D//调用RBL内部初始化函数 LPS Setting PSC10x000100060x010100030x5853590D0x000100060x01020003…………………… //0x58535901//Section Load0x80000000//编译时我们指定的地址0x00000200//Section 的大小0x003C30F6//从这里开始是我们Section的数据, 也就是我们真正的程序的数据…………0x58535901//在我们的程序里会有很多的段0x80000F000x00002440………… //从这里开始是我们Section的数据…………0x58535906//Bin文件结束,当RBL扫描到这个命令后就会结束引导并跳转0x80003160再仔细的看一下“Using the TMS320C674x BootLoader.pdf”这篇文档,你就会对Boot过程有一个很好的理解!!

word0x80000000 SMPP协议java如何写

OD中的一些符号代表什么意思呢

eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。

比方说:add eax,-2 ; //可以认为是给变量eax加上-2这样的一个值。

这些32位寄存器有多种用途,但每一个都有“专长”,有各自的特别之处。

EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。

EBX 是"基地址"(base)寄存器, 在内存寻址时存放基地址。

ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。

EDX 则总是被用来放整数除法产生的余数。

ESI/EDI分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.

EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码:

  

  push ebp ;保存当前ebp

  mov ebp,esp ;EBP设为当前堆栈指针

  sub esp, xxx ;预留xxx字节给函数临时变量.

  ...

  

  这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作 mov esp,ebp/pop ebp/ret 即可.

ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。

TC中出现Linker Error: Undefined symbol

TC 中的嵌入式汇编使用asm,而不是 __asm,

并且不能在TC环境下编译连接,需要用命令行编译器TCC编译。

而且你上面的程序肯定功能不能通过Build, 如果通过的话run就不需要再连接了。你只是通过了主模块的编译,并没有连接, build包括compile和link,Run前将检查是否通过了连接,若没有才会去连接。

谁有C语言位运算的一些练习呢,发给我

/*

* bang - Compute !x without using !

* Examples: bang(3) = 0, bang(0) = 1

* Legal ops: ~ & ^ | + << >>

* Max ops: 12

* Rating: 4

*/

int bang(int x) {

int a,b,c;

a = (~x+1);

b = a>>31;

c = x>>31;

return 1&~((b&1)|(c&1));

}

/*

* bitCount - returns count of number of 1's in word

* Examples: bitCount(5) = 2, bitCount(7) = 3

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 40

* Rating: 4

*/

int bitCount(int x) {

int a = 255+(255<<8);

int b = a^(a<<8);

int c = b^(b<<4);

int d = c^(c<<2);

int e = d^(d<<1);

x = (x&e)+((x>>1)&e);

x = (x&d)+((x>>2)&d);

x = (x&c)+((x>>4)&c);

x = (x&b)+((x>>8)&b);

x = (x&a)+((x>>16)&a);

return x;

}

/*

* copyLSB - set all bits of result to least significant bit of x

* Example: copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 5

* Rating: 2

*/

int copyLSB(int x) {

return ~(x&1)+1;

}

/*

* divpwr2 - Compute x/(2^n), for 0 <= n <= 30

* Round toward zero

* Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 15

* Rating: 2

*/

int divpwr2(int x, int n) {

int a=(x>>31)&1;

return (x+(a<<n)+~a+1)>>n;

}

/*

* evenBits - return word with all even-numbered bits set to 1

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 8

* Rating: 2

*/

int evenBits(void) {

return (85<<24)+(85<<16)+(85<<8)+85;

/*or (85<<12)|(85<<8)|(85<<4)|85); */

}

/*

* fitsBits - return 1 if x can be represented as an

* n-bit, two's complement integer.

* 1 <= n <= 32

* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 15

* Rating: 2

*/

int fitsBits(int x, int n) {

int y = x>>(n+~1+1);

return !y^!(~y);

}

/*

* getByte - Extract byte n from word x

* Bytes numbered from 0 (LSB) to 3 (MSB)

* Examples: getByte(0x12345678,1) = 0x56

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 6

* Rating: 2

*/

int getByte(int x, int n) {

int y = x>>(n<<3);

return y&255;

}

/*

* isGreater - if x > y then return 1, else return 0

* Example: isGreater(4,5) = 0, isGreater(5,4) = 1

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 24

* Rating: 3

*/

int isGreater(int x, int y) {

int z = x+~y+1;

int x1 = (x>>31)&1;

int y1 = (y>>31)&1;

int z1 = (z>>31)&1;

int k = (x1^y1)&(z1^x1);

return (!k&(!z1+~(!z)+1))|(z1&k);

}

/*

* isNonNegative - return 1 if x >= 0, return 0 otherwise

* Example: isNonNegative(-1) = 0. isNonNegative(0) = 1.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 6

* Rating: 3

*/

int isNonNegative(int x){

int a = x>>31;

return !(a&1);

}

/*

* isNotEqual - return 0 if x == y, and 1 otherwise

* Examples: isNotEqual(5,5) = 0, isNotEqual(4,5) = 1

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 6

* Rating: 2

*/

int isNotEqual(int x, int y) {

int z = x+~y+1;

return !!z;

}

/*

* isPower2 - returns 1 if x is a power of 2, and 0 otherwise

* Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0

* Note that no negative number is a power of 2.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 60

* Rating: 4

*/

int isPower2(int x) {

int y =x>>31;

return (!!x)&!(1&y)&!(x&(x+(~1)+1));

}

/*

* log2 - return floor(log base 2 of x), where x > 0

* Example: log2(16) = 4

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 90

* Rating: 4

*/

int log2(int x) {

int y = x;

int j = !!y;

int h = (j<<31)>>31;

int n = 1;

int k = !(x>>16);

int s = (k<<31)>>31;

x = ((~s)&x)+(s&(x<<16));

n = n+(s&16);

k = !(x>>24);

s = (k<<31)>>31;

x = (~s&x)+(s&(x<<8));

n = n+(s&8);

k = !(x>>28);

s = (k<<31)>>31;

x = (~s&x)+(s&(x<<4));

n = n+(s&4);

k = !(x>>30);

s = (k<<31)>>31;

x = (~s&x)+(s&(x<<2));

n = n+(s&2);

return h&(31+!!(x>>31)+(~n+1));

}

/*

* logicalShift - shift x to the right by n, using a logical shift

* Can assume that 1 <= n <= 31

* Examples: logicalShift(0x87654321,4) = 0x08765432

* Legal ops: ~ & ^ | + << >>

* Max ops: 16

* Rating: 3

*/

int logicalShift(int x, int n) {

int y = 1<<(31+~n+1);

int z = y|(y+~1+1);

int a = x>>n;

return a&z;

}

/*

* satAdd - adds two numbers but when positive overflow occurs, returns

* maximum possible value, and when negative overflow occurs,

* it returns minimum positive value.

* Examples: satAdd(0x40000000,0x40000000) = 0x7fffffff

* satAdd(0x80000000,0xffffffff) = 0x80000000

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 30

* Rating: 4

*/

int satAdd(int x, int y){

int z = x+y;

int x1 = (x>>31)&1;

int y1 = (y>>31)&1;

int z1 = (z>>31)&1;

int xy = !(x1^y1);

int k = xy&(z1^x1);

int a = k<<31;

int b =a|(a+~k+1);

int maxP = a+~1+1;

return (~b&z)|(b&(maxP+!z1));

}

/*

* tc2sm - Convert from two's complement to sign-magnitude

* where the MSB is the sign bit

* You can assume that x > TMin

* Example: tc2sm(-5) = 0x80000005.

* Legal ops: ! ~ & ^ | + << >>

* Max ops: 15

* Rating: 4

*/

int tc2sm(int x) {

int y = x >> 31 ;

int sign = y&1;

int mag = (x+y)^y;

return (sign << 31) | mag;

}

如何让linux重新枚举pci设备

  在Linux下,lspci可以枚举所有PCI设备。它是通过读取PCI配置空间(PCI Configuration Space)信息来实现PCI设备的枚举的。这里,我通过两种方式来简单的模拟一下lspci的功能。一种是通过PCI总线的CF8和CFC端口来枚举(参考PCI总线规范);另一种是利用proc filesystem。

  方法一:这种方法需要对端口进行操作,在Linux下,普通应用程序没有权限读写I/O 端口,需要通过iopl或ioperm来提升权限,我的代码里面使用iopl。

  

  [cpp] view plaincopyprint?

  /*

  * Enum all pci device via the PCI config register(CF8 and CFC).

  */

  #include <stdio.h>

  #include <stdlib.h>

  #include <unistd.h>

  #include <sys/io.h>

  

  #define PCI_MAX_BUS 255 /* 8 bits (0 ~ 255) */

  #define PCI_MAX_DEV 31 /* 5 bits (0 ~ 31) */

  #define PCI_MAX_FUN 7 /* 3 bits (0 ~ 7) */

  

  #define CONFIG_ADDRESS 0xCF8

  #define CONFIG_DATA 0xCFC

  

  #define PCICFG_REG_VID 0x00 /* Vendor id, 2 bytes */

  #define PCICFG_REG_DID 0x02 /* Device id, 2 bytes */

  #define PCICFG_REG_CMD 0x04 /* Command register, 2 bytes */

  #define PCICFG_REG_STAT 0x06 /* Status register, 2 bytes */

  #define PCICFG_REG_RID 0x08 /* Revision id, 1 byte */

  

  

  void list_pci_devices()

  {

  unsigned int bus, dev, fun;

  unsigned int addr, data;

  

  //printf("BB:DD:FF VID:DID\n");

  

  

  for (bus = 0; bus <= PCI_MAX_BUS; bus++) {

  for (dev = 0; dev <= PCI_MAX_DEV; dev++) {

  for (fun = 0; fun <= PCI_MAX_FUN; fun++) {

  addr = 0x80000000L | (bus<<16) | (dev<<11) | (fun<<8);

  outl(addr, CONFIG_ADDRESS);

  data = inl(CONFIG_DATA);

  

  /* Identify vendor ID */

  if ((data != 0xFFFFFFFF) && (data != 0)) {

  printf("%02X:%02X:%02X ", bus, dev, fun);

  printf("%04X:%04X", data&0xFFFF, data>>16);

  addr = 0x80000000L | (bus<<16) | (dev<<11) | (fun<<8) | PCICFG_REG_RID;

  outl(addr, CONFIG_ADDRESS);

  data = inl(CONFIG_DATA);

  if (data&0xFF) {

  printf(" (rev %02X)\n", data&0xFF);

  } else {

  printf("\n");

  }

  }

  } end func

  } // end device

  } // end bus

  }

  

  

  int main()

  {

  int ret;

  

  /* Enable r/w permission of all 65536 ports */

  ret = iopl(3);

  if (ret < 0) {

  perror("iopl set error");

  return 1;

  }

  

  list_pci_devices();

  

  /* Disable r/w permission of all 65536 ports */

  ret = iopl(0);

  if (ret < 0) {

  perror("iopl set error");

  return 1;

  }

  

  return 0;

  }

  方法二:这种方法需不需要对端口进行操作,而是利用Linux procfs来实现对PCI 配置空间的访问。

  [cpp] view plaincopyprint?

  /*

  * Enum all pci device via /proc/bus/pci/.

  */

  #include <stdio.h>

  #include <stdint.h>

  #include <stdlib.h>

  #include <string.h>

  #include <fcntl.h>

  #include <unistd.h>

  

  #define PCI_MAX_BUS 255 /* 8 bits (0 ~ 255) */

  #define PCI_MAX_DEV 31 /* 5 bits (0 ~ 31) */

  #define PCI_MAX_FUN 7 /* 3 bits (0 ~ 7) */

  

  /*

  * PCI Configuration Header offsets

  */

  #define PCICFG_REG_VID 0x00 /* Vendor id, 2 bytes */

  #define PCICFG_REG_DID 0x02 /* Device id, 2 bytes */

  #define PCICFG_REG_CMD 0x04 /* Command register, 2 bytes */

  #define PCICFG_REG_STAT 0x06 /* Status register, 2 bytes */

  #define PCICFG_REG_RID 0x08 /* Revision id, 1 byte */

  #define PCICFG_REG_PROG_INTF 0x09 /* Programming interface code, 1 byte */

  #define PCICFG_REG_SUBCLASS 0x0A /* Sub-class code, 1 byte */

  #define PCICFG_REG_BASCLASS 0x0B /* Base class code, 1 byte */

  #define PCICFG_REG_CACHE_LINESZ 0x0C /* Cache line size, 1 byte */

  #define PCICFG_REG_LATENCY_TIMER 0x0D /* Latency timer, 1 byte */

  #define PCICFG_REG_HEADER_TYPE 0x0E /* Header type, 1 byte */

  #define PCICFG_REG_BIST 0x0F /* Builtin self test, 1 byte */

  #define PCICFG_REG_BAR0 0x10 /* Base addr register 0, 4 bytes */

  #define PCICFG_REG_BAR1 0x14 /* Base addr register 1, 4 bytes */

  #define PCICFG_REG_BAR2 0x18 /* Base addr register 2, 4 bytes */

  #define PCICFG_REG_BAR3 0x1C /* Base addr register 3, 4 bytes */

  #define PCICFG_REG_BAR4 0x20 /* Base addr register 4, 4 bytes */

  #define PCICFG_REG_BAR5 0x24 /* Base addr register 5, 4 bytes */

  #define PCICFG_REG_CIS 0x28 /* Cardbus CIS Pointer */

  #define PCICFG_REG_SVID 0x2C /* Subsystem Vendor ID, 2 bytes */

  #define PCICFG_REG_SDID 0x2E /* Subsystem ID, 2 bytes */

  #define PCICFG_REG_ROMBAR 0x30 /* ROM base register, 4 bytes */

  #define PCICFG_REG_CAPPTR 0x34 /* Capabilities pointer, 1 byte */

  #define PCICFG_REG_INT_LINE 0x3C /* Interrupt line, 1 byte */

  #define PCICFG_REG_INT_PIN 0x3D /* Interrupt pin, 1 byte */

  #define PCICFG_REG_MIN_GNT 0x3E /* Minimum grant, 1 byte */

  #define PCICFG_REG_MAX_LAT 0x3F /* Maximum lat, 1 byte */

  

  

  void list_pci_devices()

  {

  unsigned int bus, dev, fun;

  

  //printf("BB:DD:FF VID:DID(RID)\n");

  

  

  for (bus = 0; bus <= PCI_MAX_BUS; bus++) {

  for (dev = 0; dev <= PCI_MAX_DEV; dev++) {

  for (fun = 0; fun <= PCI_MAX_FUN; fun++) {

  char proc_name[64];

  int cfg_handle;

  uint32_t data;

  uint16_t vid, did;

  uint8_t rid;

  

  snprintf(proc_name, sizeof(proc_name),

  "/proc/bus/pci/%02x/%02x.%x", bus, dev, fun);

  cfg_handle = open(proc_name, O_RDWR);

  if (cfg_handle <= 0)

  continue;

  

  lseek(cfg_handle, PCICFG_REG_VID, SEEK_SET);

  read(cfg_handle, &data, sizeof(data));

  

  /* Identify vendor ID */

  if ((data != 0xFFFFFFFF) && (data != 0)) {

  lseek(cfg_handle, PCICFG_REG_RID, SEEK_SET);

  read(cfg_handle, &rid, sizeof(rid));

  vid = data&0xFFFF;

  did = data>>16;

  

  printf("%02X:%02X:%02X", bus, dev, fun);

  if (rid > 0) {

  printf(" %04X:%04X (rev %02X)\n", vid, did, rid);

  } else {

  printf(" %04X:%04X\n", vid, did);

  }

  }

  } // end func

  } // end device

  } // end bus

  }

  

  int main(int argc, char **argv)

  {

  list_pci_devices();

  

  return 0;

  }

  

  这两种方法各有优缺点,第一种方法方便移植到其他OS,第二种就只适用于Linux。但是,第一种方法需要对I/O port进行直接操作。第二种就不需要。

  注意:执行这两段代码时,需要超级用户(root) 权限。

  补充:今天在枚举 Westmere-EP Processor(Intel Xeon Processor 5500 Series(Nehalem-EP))的 IMC(Integrated Memory Controller)时发现一个问题。lspci无法枚举到IMC设备。Westmere-EP 是 Intel 新的处理器架构。和以往的CPU不一样,它把Memory Controller集成到了CPU里面。IMC控制器被映射到了PCI总线上,Bus Number 是0xFE~0xFF,procfs(/proc/bus/pci/)下没有这几个设备。但是,通过 CF8/CFC 端口可以枚举到这些设备。

  3. 这段代码是在驱动中可以用来查找特定的pci device,并且返回一个pci_dev的结构体变量。通过这样一个struct变量,内核提供的接口函数可以直接套用,如pci_read_config_word(),pci_write_config_word()等。

  [cpp] view plaincopyprint?

  void list_pci_device()

  {

  struct pci_dev *dev;

  struct pci_bus *bus,*childbus;

  

  list_for_each_entry(bus, &pci_root_buses, node) { //globle pci_root_buses in pci.h

  list_for_each_entry(dev, &bus->devices, bus_list) { // for bus 0

  printk("%02X:%02X:%02X %04X:%04X\n",dev->bus->number,dev->devfn >> 3, dev->devfn & 0x07,dev->vendor,dev->device);

  }

  list_for_each_entry(childbus, &bus->children,node) { // for bus 1,2,3,...

  list_for_each_entry(dev, &childbus->devices, bus_list) {

  printk("%02X:%02X:%02X %04X:%04X\n",dev->bus->number,dev->devfn >> 3, dev->devfn & 0x07,dev->vendor,dev->device);

  }

  }

  }

vc怎样实现后台捕捉键盘消息,且能区分按下和放开.

后台捕捉可以采用键盘钩子KeyboardProc函数实现。可以到百度百科中自己科普一下。

函数有三个参数: KeyBoardProc (int nCode, WORD wParam, DWORD lParam)

判断第三个参数来确定是否是按键按下

if (lParam & 0x80000000)

//按键放开

else

//按键按下

转载请注明出处51数据库 » word0x80000000 SMPP协议java如何写

软件
前端设计
程序设计
Java相关