XWOS API  4.0
XWOS C/C++ API参考手册
载入中...
搜索中...
未找到
controller.c
浏览该文件的文档.
1
29#include <xwcd/ds/standard.h>
30#include <string.h>
32#include <xwos/osal/lock/mtx.h>
33#include <xwos/osal/sync/sem.h>
35
36static __xwds_vop
38
39static __xwds_vop
41
42static __xwds_vop
44
45static __xwds_vop
47
48#if defined(XWCDCFG_ds_PM) && (1 == XWCDCFG_ds_PM)
49static __xwds_vop
51
52static __xwds_vop
54#endif
55
57 .probe = (void *)xwds_uartc_vop_probe,
59 .start = (void *)xwds_uartc_vop_start,
60 .stop = (void *)xwds_uartc_vop_stop,
61#if defined(XWCDCFG_ds_PM) && (1 == XWCDCFG_ds_PM)
62 .suspend = (void *)xwds_uartc_vop_suspend,
64#endif
65};
66
67/******** ******** ******** constructor & destructor ******** ******** ********/
73void xwds_uartc_construct(struct xwds_uartc * uartc)
74{
76 uartc->dev.vop = &xwds_uartc_vop;
77}
78
84void xwds_uartc_destruct(struct xwds_uartc * uartc)
85{
87}
88
95{
96 return xwds_device_grab(&uartc->dev);
97}
98
105{
106 return xwds_device_put(&uartc->dev);
107}
108
109/******** ******** base virtual operations ******** ********/
114static __xwds_vop
116{
117 xwer_t rc;
118
119 xwos_splk_init(&uartc->rxq.lock);
120 rc = xwos_sem_init(&uartc->rxq.sem, 0, 1);
121 if (rc < 0) {
122 goto err_sem_init;
123 }
125 if (rc < 0) {
126 goto err_txmtx_init;
127 }
128 rc = xwds_device_vop_probe(&uartc->dev);
129 if (rc < 0) {
130 goto err_dev_probe;
131 }
132 return XWOK;
133
134err_dev_probe:
135 xwos_mtx_fini(&uartc->txmtx);
136err_txmtx_init:
137 xwos_sem_fini(&uartc->rxq.sem);
138err_sem_init:
139 return rc;
140}
141
146static __xwds_vop
148{
149 xwer_t rc;
150
151 rc = xwds_device_vop_remove(&uartc->dev);
152 if (rc < 0) {
153 goto err_dev_vop_remove;
154 }
155
156 xwos_mtx_fini(&uartc->txmtx);
157 xwos_sem_fini(&uartc->rxq.sem);
158 return XWOK;
159
160err_dev_vop_remove:
161 return rc;
162}
163
168static __xwds_vop
170{
171 xwer_t rc;
172
173 memset(uartc->rxq.mem, 0, sizeof(uartc->rxq.mem));
174 uartc->rxq.pos = 0;
175 uartc->rxq.tail = 0;
176 uartc->rxq.idx = 0;
177
178 rc = xwds_device_vop_start(&uartc->dev);
179 return rc;
180}
181
186static __xwds_vop
188{
189 xwer_t rc;
190
191 rc = xwds_device_vop_stop(&uartc->dev);
192 return rc;
193}
194
195#if (defined(XWCDCFG_ds_PM)) && (1 == XWCDCFG_ds_PM)
196/******** ******** pm ******** ********/
201static __xwds_vop
203{
204 xwer_t rc;
205
206 rc = xwds_device_vop_suspend(&uartc->dev);
207 return rc;
208}
209
214static __xwds_vop
216{
217 xwer_t rc;
218
219 memset(uartc->rxq.mem, 0, sizeof(uartc->rxq.mem));
220 uartc->rxq.pos = 0;
221 uartc->rxq.tail = 0;
222 rc = xwds_device_vop_resume(&uartc->dev);
223 return rc;
224}
225#endif
226
227/******** ******** ******** UART APIs ******** ******** ********/
230 xwu8_t * buf, xwsz_t * size,
231 xwtm_t to)
232{
233 xwsz_t available, real, cp, rest_buffer_size;
234 xwsq_t pos;
235 xwreg_t cpuirq;
236 xwer_t rc;
237
238 XWDS_VALIDATE(uartc, "nullptr", -EFAULT);
239 XWDS_VALIDATE(buf, "nullptr", -EFAULT);
240 XWDS_VALIDATE(size, "nullptr", -EFAULT);
241
242 pos = 0;
243 rc = xwds_uartc_grab(uartc);
244 if (rc < 0) {
245 goto err_uartc_grab;
246 }
247 rest_buffer_size = *size;
248 while (rest_buffer_size) {
249 rc = xwos_sem_wait_to(&uartc->rxq.sem, to);
250 if (rc < 0) {
251 goto err_sem_wait_to;
252 }
253 xwos_splk_lock_cpuirqsv(&uartc->rxq.lock, &cpuirq);
254 if (uartc->rxq.tail >= uartc->rxq.pos) {
255 available = uartc->rxq.tail - uartc->rxq.pos;
256 } else {
257 available = sizeof(uartc->rxq.mem) - uartc->rxq.pos;
258 available += uartc->rxq.tail;
259 }
260 real = available > rest_buffer_size ? rest_buffer_size : available;
261 if ((real + uartc->rxq.pos) >= sizeof(uartc->rxq.mem)) {
262 cp = sizeof(uartc->rxq.mem) - uartc->rxq.pos;
263 memcpy(&buf[pos], &uartc->rxq.mem[uartc->rxq.pos], cp);
264 memcpy(&buf[cp + pos], &uartc->rxq.mem[0], real - cp);
265 uartc->rxq.pos = real - cp;
266 } else {
267 memcpy(&buf[pos], &uartc->rxq.mem[uartc->rxq.pos], real);
268 uartc->rxq.pos += real;
269 }
270 xwos_splk_unlock_cpuirqrs(&uartc->rxq.lock, cpuirq);
271 pos += real;
272 rest_buffer_size -= real;
273 if (available > real) {
274 xwos_sem_post(&uartc->rxq.sem);
275 }
276 }
277 xwds_uartc_put(uartc);
278 *size = pos;
279 return XWOK;
280
281err_sem_wait_to:
282 xwds_uartc_put(uartc);
283err_uartc_grab:
284 *size = pos;
285 return rc;
286}
287
290 xwu8_t * buf, xwsz_t * size)
291{
292 xwsz_t available, real, cp, rest_buffer_size;
293 xwsq_t pos;
294 xwreg_t cpuirq;
295 xwer_t rc;
296
297 XWDS_VALIDATE(uartc, "nullptr", -EFAULT);
298 XWDS_VALIDATE(buf, "nullptr", -EFAULT);
299 XWDS_VALIDATE(size, "nullptr", -EFAULT);
300
301 pos = 0;
302 rc = xwds_uartc_grab(uartc);
303 if (rc < 0) {
304 goto err_uartc_grab;
305 }
306 rest_buffer_size = *size;
307 while (rest_buffer_size) {
308 rc = xwos_sem_trywait(&uartc->rxq.sem);
309 if (rc < 0) {
310 goto err_sem_trywait;
311 }
312 xwos_splk_lock_cpuirqsv(&uartc->rxq.lock, &cpuirq);
313 if (uartc->rxq.tail >= uartc->rxq.pos) {
314 available = uartc->rxq.tail - uartc->rxq.pos;
315 } else {
316 available = sizeof(uartc->rxq.mem) - uartc->rxq.pos;
317 available += uartc->rxq.tail;
318 }
319 real = available > rest_buffer_size ? rest_buffer_size : available;
320 if ((real + uartc->rxq.pos) >= sizeof(uartc->rxq.mem)) {
321 cp = sizeof(uartc->rxq.mem) - uartc->rxq.pos;
322 memcpy(&buf[pos], &uartc->rxq.mem[uartc->rxq.pos], cp);
323 memcpy(&buf[cp + pos], &uartc->rxq.mem[0], real - cp);
324 uartc->rxq.pos = real - cp;
325 } else {
326 memcpy(&buf[pos], &uartc->rxq.mem[uartc->rxq.pos], real);
327 uartc->rxq.pos += real;
328 }
329 xwos_splk_unlock_cpuirqrs(&uartc->rxq.lock, cpuirq);
330 pos += real;
331 rest_buffer_size -= real;
332 if (available > real) {
333 xwos_sem_post(&uartc->rxq.sem);
334 }
335 }
336 xwds_uartc_put(uartc);
337 *size = pos;
338 return XWOK;
339
340err_sem_trywait:
341 xwds_uartc_put(uartc);
342err_uartc_grab:
343 *size = pos;
344 return rc;
345}
346
349 const xwu8_t * data, xwsz_t * size,
350 xwtm_t to)
351{
352 const struct xwds_uartc_driver * drv;
353 xwer_t rc;
354
355 XWDS_VALIDATE(uartc, "nullptr", -EFAULT);
356 XWDS_VALIDATE(data, "nullptr", -EFAULT);
357 XWDS_VALIDATE(size, "nullptr", -EFAULT);
358
359 rc = xwds_uartc_grab(uartc);
360 if (rc < 0) {
361 goto err_uartc_grab;
362 }
363 rc = xwos_mtx_lock_to(&uartc->txmtx, to);
364 if (rc < 0) {
365 goto err_uartc_lock;
366 }
367 drv = xwds_cast(const struct xwds_uartc_driver *, uartc->dev.drv);
368 if ((drv) && (drv->tx)) {
369 rc = drv->tx(uartc, data, size, to);
370 } else {
371 rc = -ENOSYS;
372 }
373 if (rc < 0) {
374 goto err_tx;
375 }
376 xwos_mtx_unlock(&uartc->txmtx);
377 xwds_uartc_put(uartc);
378 return XWOK;
379
380err_tx:
381 xwos_mtx_unlock(&uartc->txmtx);
382err_uartc_lock:
383 xwds_uartc_put(uartc);
384err_uartc_grab:
385 return rc;
386}
387
390 const xwu8_t * data, xwsz_t * size,
392{
393 const struct xwds_uartc_driver * drv;
394 xwer_t rc;
395
396 XWDS_VALIDATE(uartc, "nullptr", -EFAULT);
397 XWDS_VALIDATE(data, "nullptr", -EFAULT);
398 XWDS_VALIDATE(size, "nullptr", -EFAULT);
399
400 rc = xwds_uartc_grab(uartc);
401 if (rc < 0) {
402 goto err_uartc_grab;
403 }
404 drv = xwds_cast(const struct xwds_uartc_driver *, uartc->dev.drv);
405 if ((drv) && (drv->eq)) {
406 rc = drv->eq(uartc, data, size, cb);
407 } else {
408 rc = -ENOSYS;
409 }
410 if (rc < 0) {
411 goto err_eq;
412 }
413 xwds_uartc_put(uartc);
414 return XWOK;
415
416err_eq:
417 xwds_uartc_put(uartc);
418err_uartc_grab:
419 return rc;
420}
421
424 const xwu8_t byte,
425 xwtm_t to)
426{
427 xwer_t rc;
428 const struct xwds_uartc_driver * drv;
429
430 XWDS_VALIDATE(uartc, "nullptr", -EFAULT);
431
432 rc = xwds_uartc_grab(uartc);
433 if (rc < 0) {
434 goto err_uartc_grab;
435 }
436 rc = xwos_mtx_lock_to(&uartc->txmtx, to);
437 if (rc < 0) {
438 goto err_uartc_lock;
439 }
440 drv = xwds_cast(const struct xwds_uartc_driver *, uartc->dev.drv);
441 if ((drv) && (drv->putc)) {
442 rc = drv->putc(uartc, byte);
443 } else {
444 rc = -ENOSYS;
445 }
446 if (rc < 0) {
447 goto err_putc;
448 }
449 xwos_mtx_unlock(&uartc->txmtx);
450 xwds_uartc_put(uartc);
451 return XWOK;
452
453err_putc:
454 xwos_mtx_unlock(&uartc->txmtx);
455err_uartc_lock:
456 xwds_uartc_put(uartc);
457err_uartc_grab:
458 return rc;
459}
460
463 const struct xwds_uart_cfg * cfg)
464{
465 const struct xwds_uartc_driver * drv;
466 xwer_t rc;
467
468 XWDS_VALIDATE(uartc, "nullptr", -EFAULT);
469 XWDS_VALIDATE(cfg, "nullptr", -EFAULT);
470
471 rc = xwds_uartc_grab(uartc);
472 if (rc < 0) {
473 goto err_uartc_grab;
474 }
475 drv = xwds_cast(const struct xwds_uartc_driver *, uartc->dev.drv);
476 if ((drv) && (drv->cfg)) {
477 rc = drv->cfg(uartc, cfg);
478 } else {
479 rc = -ENOSYS;
480 }
481 if (rc < 0) {
482 goto err_drv_cfg;
483 }
484 xwds_uartc_put(uartc);
485 return XWOK;
486
487err_drv_cfg:
488 xwds_uartc_put(uartc);
489err_uartc_grab:
490 return rc;
491}
492
493/******** ******** Callbacks for driver ******** ********/
496{
497 xwreg_t cpuirq;
498
499 xwos_sem_trywait(&uartc->rxq.sem);
500 xwos_splk_lock_cpuirqsv(&uartc->rxq.lock, &cpuirq);
501 uartc->rxq.pos = 0;
502 uartc->rxq.tail = 0;
503 uartc->rxq.idx = 0;
504 xwos_splk_unlock_cpuirqrs(&uartc->rxq.lock, cpuirq);
505}
506
509 xwu8_t bytes[], xwsz_t size)
510{
511 for (xwsz_t i = 0; i < size; i++) {
512 uartc->rxq.mem[uartc->rxq.idx] = bytes[i];
513 uartc->rxq.idx++;
514 if (sizeof(uartc->rxq.mem) == uartc->rxq.idx) {
515 uartc->rxq.idx = 0;
516 }
517 }
518 return uartc->rxq.idx;
519}
520
523{
524 xwsz_t pubsz;
525 xwreg_t cpuirq;
526
527 if (sizeof(uartc->rxq.mem) == pub) {
528 pub = 0;
529 }
530 xwos_splk_lock_cpuirqsv(&uartc->rxq.lock, &cpuirq);
531 if (pub == uartc->rxq.tail) {
532 pubsz = 0;
533 } else if (pub > uartc->rxq.tail) {
534 pubsz = pub - uartc->rxq.tail;
535 if (uartc->rxq.pos <= uartc->rxq.tail) {
536 } else if (uartc->rxq.pos <= pub) {
537 /* Overflow! Discard the oldest data. */
538 uartc->rxq.pos = pub + 1;
539 if (sizeof(uartc->rxq.mem) == uartc->rxq.pos) {
540 uartc->rxq.pos = 0;
541 }
542 } else {
543 }
544 uartc->rxq.tail = pub;
545 } else {
546 pubsz = sizeof(uartc->rxq.mem) - uartc->rxq.tail + pub;
547 if (uartc->rxq.pos <= pub) {
548 /* Overflow! Discard the oldest data. */
549 uartc->rxq.pos = pub + 1;
550 /* `uartc->rxq.pos < sizeof(uartc->rxq.mem)` is always true. */
551 } else if (uartc->rxq.pos <= uartc->rxq.tail) {
552 } else {
553 /* Overflow! Discard the oldest data. */
554 uartc->rxq.pos = pub + 1;
555 /* `uartc->rxq.pos < sizeof(uartc->rxq.mem)` is always true. */
556 }
557 uartc->rxq.tail = pub;
558 }
559 xwos_splk_unlock_cpuirqrs(&uartc->rxq.lock, cpuirq);
560 if (pubsz > 0) {
561 xwos_sem_post(&uartc->rxq.sem);
562 }
563}
static xwer_t xwds_device_grab(struct xwds_device *dev)
XWDS API:增加对象的引用计数
Definition device.h:268
xwer_t xwds_device_vop_start(struct xwds_device *dev)
设备基本操作函数:启动设备
Definition device.c:105
void xwds_device_construct(struct xwds_device *dev)
XWDS API:设备的构造函数
Definition device.c:48
void xwds_device_destruct(struct xwds_device *dev)
XWDS API:设备的析构函数
Definition device.c:56
static xwer_t xwds_device_put(struct xwds_device *dev)
XWDS API:减少对象的引用计数
Definition device.h:281
xwer_t xwds_device_vop_stop(struct xwds_device *dev)
设备基本操作函数:停止设备
Definition device.c:124
xwer_t xwds_device_vop_remove(struct xwds_device *dev)
设备基本操作函数:删除设备
Definition device.c:86
xwer_t xwds_device_vop_resume(struct xwds_device *dev)
设备基本操作函数:继续设备
Definition device.c:163
xwer_t xwds_device_vop_probe(struct xwds_device *dev)
设备基本操作函数:探测设备
Definition device.c:67
xwer_t xwds_device_vop_suspend(struct xwds_device *dev)
设备基本操作函数:暂停设备
Definition device.c:144
xwer_t xwds_uartc_grab(struct xwds_uartc *uartc)
增加对象的引用计数
Definition controller.c:94
xwer_t xwds_uartc_tx(struct xwds_uartc *uartc, const xwu8_t *data, xwsz_t *size, xwtm_t to)
XWDS API:同步发送
Definition controller.c:348
void xwds_uartc_drvcb_rxq_pub(struct xwds_uartc *uartc, xwsq_t pub)
XWDS Driver Callback:发布数据到接收队列
Definition controller.c:522
xwer_t xwds_uartc_cfg(struct xwds_uartc *uartc, const struct xwds_uart_cfg *cfg)
XWDS API:配置UART
Definition controller.c:462
void xwds_uartc_destruct(struct xwds_uartc *uartc)
XWDS API:UART控制器对象的析构函数
Definition controller.c:84
xwer_t xwds_uartc_rx(struct xwds_uartc *uartc, xwu8_t *buf, xwsz_t *size, xwtm_t to)
XWDS API:从接收队列中获取数据
Definition controller.c:229
void xwds_uartc_construct(struct xwds_uartc *uartc)
XWDS API:UART控制器的构造函数
Definition controller.c:73
xwer_t xwds_uartc_eq(struct xwds_uartc *uartc, const xwu8_t *data, xwsz_t *size, xwds_uartc_eqcb_f cb)
XWDS API:异步发送
Definition controller.c:389
xwer_t xwds_uartc_put(struct xwds_uartc *uartc)
减少对象的引用计数
Definition controller.c:104
xwer_t xwds_uartc_putc(struct xwds_uartc *uartc, const xwu8_t byte, xwtm_t to)
XWDS API:直接发送一个字节(非DMA模式)
Definition controller.c:423
void(* xwds_uartc_eqcb_f)(struct xwds_uartc *, xwer_t)
异步发送的回调函数类型
Definition controller.h:171
xwsq_t xwds_uartc_drvcb_rxq_fill(struct xwds_uartc *uartc, xwu8_t bytes[], xwsz_t size)
XWDS Driver Callback:从UART硬件接收数据到缓冲区
Definition controller.c:508
void xwds_uartc_drvcb_rxq_flush(struct xwds_uartc *uartc)
XWDS Driver Callback:清空接收队列
Definition controller.c:495
xwer_t xwds_uartc_try_rx(struct xwds_uartc *uartc, xwu8_t *buf, xwsz_t *size)
XWDS API:尝试从接收队列中获取数据
Definition controller.c:289
#define xwds_cast(type, dev)
Definition standard.h:40
#define __xwds_vop
Definition standard.h:36
#define __xwds_code
Definition standard.h:31
#define __xwds_api
Definition standard.h:33
#define XWDS_VALIDATE(exp, errstr,...)
Definition standard.h:51
#define __xwds_rodata
Definition standard.h:38
#define EFAULT
Bad address
Definition errno.h:44
#define ENOSYS
Function not implemented
Definition errno.h:110
#define XWOK
No error
Definition errno.h:182
xws64_t xwtm_t
XWOS系统时间 (有符号)
Definition type.h:742
signed long xwer_t
Definition type.h:554
unsigned long xwsz_t
Definition type.h:339
uint8_t xwu8_t
Definition type.h:194
unsigned long xwsq_t
Definition type.h:445
xwptr_t xwreg_t
Definition type.h:409
static xwer_t xwos_mtx_init(struct xwos_mtx *mtx, xwpr_t sprio)
XWOS API:静态方式初始化互斥锁
Definition mtx.h:111
static xwer_t xwos_mtx_lock_to(struct xwos_mtx *mtx, xwtm_t to)
XWOS API:限时等待上锁互斥锁
Definition mtx.h:329
static xwer_t xwos_mtx_fini(struct xwos_mtx *mtx)
XWOS API:销毁静态方式初始化的互斥锁
Definition mtx.h:126
static xwer_t xwos_mtx_unlock(struct xwos_mtx *mtx)
XWOS API:解锁互斥锁
Definition mtx.h:279
static void xwos_splk_unlock_cpuirqrs(struct xwos_splk *spl, xwreg_t cpuirq)
XWOS API:解锁自旋锁,并恢复本地CPU的中断标志
Definition spinlock.h:224
static void xwos_splk_init(struct xwos_splk *spl)
XWOS API:初始化自旋锁
Definition spinlock.h:89
static void xwos_splk_lock_cpuirqsv(struct xwos_splk *spl, xwreg_t *cpuirq)
XWOS API:上锁自旋锁,保存本地CPU的中断标志并关闭
Definition spinlock.h:192
#define XWOS_SKD_PRIORITY_RT_MIN
XWOS API:最小实时优先级
Definition skd.h:89
static xwer_t xwos_sem_trywait(struct xwos_sem *sem)
XWOS API:尝试获取信号量
Definition sem.h:454
static xwer_t xwos_sem_fini(struct xwos_sem *sem)
XWOS API:销毁静态方式初始化的信号量对象
Definition sem.h:140
static xwer_t xwos_sem_wait_to(struct xwos_sem *sem, xwtm_t to)
XWOS API:限时等待并获取信号量
Definition sem.h:418
static xwer_t xwos_sem_init(struct xwos_sem *sem, xwssq_t val, xwssq_t max)
XWOS API:静态方式初始化信号量对象
Definition sem.h:125
static xwer_t xwos_sem_post(struct xwos_sem *sem)
XWOS API:发布信号量
Definition sem.h:373
操作系统抽象层:互斥锁
操作系统抽象层:自旋锁
const struct xwds_driver * drv
Definition device.h:133
const struct xwds_virtual_operation * vop
Definition device.h:138
UART配置
Definition controller.h:154
BSP中需要提供的UART控制器驱动函数表
Definition controller.h:176
xwer_t(* eq)(struct xwds_uartc *, const xwu8_t *, xwsz_t *, xwds_uartc_eqcb_f)
Definition controller.h:183
xwer_t(* cfg)(struct xwds_uartc *, const struct xwds_uart_cfg *)
Definition controller.h:178
xwer_t(* tx)(struct xwds_uartc *, const xwu8_t *, xwsz_t *, xwtm_t)
Definition controller.h:180
xwer_t(* putc)(struct xwds_uartc *, const xwu8_t)
Definition controller.h:186
UART控制器
Definition controller.h:193
struct xwds_device dev
Definition controller.h:194
xwu8_t mem[(128U)]
Definition controller.h:211
struct xwos_splk lock
Definition controller.h:207
struct xwos_sem sem
Definition controller.h:206
struct xwds_uartc::@27 rxq
xwsq_t idx
Definition controller.h:210
struct xwos_mtx txmtx
Definition controller.h:202
xwsq_t pos
Definition controller.h:208
xwsz_t tail
Definition controller.h:209
基本操作的虚函数表(类似C++的虚函数表)
Definition device.h:99
xwer_t(* stop)(struct xwds_device *)
Definition device.h:103
xwer_t(* remove)(struct xwds_device *)
Definition device.h:101
xwer_t(* probe)(struct xwds_device *)
Definition device.h:100
xwer_t(* resume)(struct xwds_device *)
Definition device.h:106
操作系统抽象层:信号量
static xwer_t xwds_uartc_vop_probe(struct xwds_uartc *uartc)
XWDS VOP:探测UART控制器
Definition controller.c:115
const struct xwds_virtual_operation xwds_uartc_vop
Definition controller.c:56
static xwer_t xwds_uartc_vop_resume(struct xwds_uartc *uartc)
XWDS VOP:继续UART控制器
Definition controller.c:215
static xwer_t xwds_uartc_vop_stop(struct xwds_uartc *uartc)
XWDS VOP:停止UART控制器
Definition controller.c:187
static xwer_t xwds_uartc_vop_remove(struct xwds_uartc *uartc)
XWDS VOP:移除UART控制器
Definition controller.c:147
static xwer_t xwds_uartc_vop_start(struct xwds_uartc *uartc)
XWDS VOP:启动UART控制器
Definition controller.c:169
static xwer_t xwds_uartc_vop_suspend(struct xwds_uartc *uartc)
XWDS VOP:暂停UART控制器
Definition controller.c:202
玄武设备栈:UART控制器
玄武设备栈:顶级头文件