📄 edb7312-usb.c
字号:
while (l--) *b++ = d12_ind(p); d12_buf_clear(p); } return len;}/* write buffer */static int d12_buf_write(struct d12 *p, int epx, const void *buf, int len){ int i, l, l2, stat; const unsigned char *b; b = (const unsigned char *)buf; if (epx == EPX_BULK_I) { stat = d12_status_get(p, epx); i = 2; if (stat & D_READ_ENDP_STAT_BUF0) i--; if (stat & D_READ_ENDP_STAT_BUF1) i--; l2 = 0; while (i-- && len) { d12_select_endpoint(p, epx); l = len; if (l > EP_BULK_SIZE) l = EP_BULK_SIZE; d12_out2(p, CMD_WRITE_BUFFER, 0, l); l2 += l; len -= l; while (l--) d12_outd(p, *b++); d12_buf_validate(p); } len = l2; } else { d12_select_endpoint(p, epx); d12_out2(p, CMD_WRITE_BUFFER, 0, len); l = len; while (l--) d12_outd(p, *b++); d12_buf_validate(p); } return len;}/* ------------------------------------------------------------------------- *//* * USB 1.1 chapter 9 broken into tiny little pieces plus a little mass-storage */static void ep_ctrl_ack(struct d12 *p){ d12_buf_write(p, EPX_CTRL_I, 0, 0); p->fsm_ctl = FSM_CTL_STATUS_IN;}static void ep_ctrl_write(struct d12 *p, const void *buf, int len){ struct devreq *drq; drq = &p->drq; if (len > drq->wLength) /* 9.3.5: return <= */ len = drq->wLength; if (len > MAX_DBUF) len = MAX_DBUF; memcpy(p->dbuf, buf, len); p->dlen = len; p->dptr = 0; if (len > EP_CTRL_SIZE) len = EP_CTRL_SIZE; d12_buf_write(p, EPX_CTRL_I, p->dbuf, len); p->dptr += len; p->fsm_ctl = (p->dptr == p->dlen) ? FSM_CTL_STATUS_OUT : FSM_CTL_DATA_IN; p->fsm_ctl_lastpkt = len;}/* --- */static int std_reserved(struct d12 *p){#ifdef DBG printk("%s: unsupported reserved request\n", ID);#endif return 1;}static int std_get_status(struct d12 *p){ struct devreq *drq; int ep, epx; unsigned char buf[2]; drq = &p->drq; if ((drq->bmRequestType & (REQTYPE_DIR_M | REQTYPE_TYPE_M)) != (REQTYPE_DIR_IN | REQTYPE_TYPE_STANDARD)) goto err; if (drq->wValue || (drq->wLength != 2)) goto err; if (p->fsm_dev == FSM_DEV_DEFAULT) goto err; buf[0] = buf[1] = 0; switch (drq->bmRequestType & REQTYPE_RECP_M) { case REQTYPE_RECP_DEVICE: if (drq->wIndex) goto err; buf[0] = STATUS_DEVICE_SELF_POWERED | (p->feat_wakeup ? STATUS_DEVICE_REMOTE_WAKEUP : 0);#ifdef DBG printk("%s: get_status device --> 0x%02x 0x%02x\n", ID, buf[0], buf[1]);#endif break; case REQTYPE_RECP_INTERFACE: if (p->fsm_dev == FSM_DEV_ADDRESS) goto err; if (drq->wIndex & 0xFF) /* only one interface */ goto err; #ifdef DBG printk("%s: get_status interface --> 0x%02x 0x%02x\n", ID, buf[0], buf[1]);#endif break; case REQTYPE_RECP_ENDPOINT: ep = drq->wIndex & 0x0F; if ((ep != EP_CTRL) && (ep != EP_BULK)) goto err; if (p->fsm_dev == FSM_DEV_ADDRESS) if (ep != EP_CTRL) goto err; epx = (ep << 1) | ((drq->wIndex & 0x80) ? 1 : 0); buf[0] = (d12_select_endpoint(p, epx) & D_SELECT_ENDP_STALL) ? STATUS_ENDPOINT_HALT : 0;#ifdef DBG printk("%s: get_status endpoint --> 0x%02x 0x%02x\n", ID, buf[0], buf[1]);#endif break; default: goto err; } ep_ctrl_write(p, buf, drq->wLength); return 0;err:#ifdef DBG printk("%s: bad get_status request\n", ID);#endif return 1;}static int feature(struct d12 *p, int on){ struct devreq *drq; int ep, epx; drq = &p->drq; if ((drq->bmRequestType & (REQTYPE_DIR_M | REQTYPE_TYPE_M)) != (REQTYPE_DIR_OUT | REQTYPE_TYPE_STANDARD)) goto err; if (drq->wLength) goto err; if (p->fsm_dev == FSM_DEV_DEFAULT) goto err; switch (drq->bmRequestType & REQTYPE_RECP_M) { case REQTYPE_RECP_DEVICE: if (drq->wIndex) goto err; if (drq->wValue == FEATURE_DEVICE_REMOTE_WAKEUP) { p->feat_wakeup = on;#ifdef DBG printk("%s: %s_feature device_remote_wakeup\n", ID, on ? "set" : "clear");#endif } else goto err; break; case REQTYPE_RECP_INTERFACE: goto err; case REQTYPE_RECP_ENDPOINT: ep = drq->wIndex & 0x0F; if ((ep != EP_CTRL) && (ep != EP_BULK)) goto err; if (p->fsm_dev == FSM_DEV_ADDRESS) if (ep != EP_CTRL) goto err; epx = (ep << 1) | ((drq->wIndex & 0x80) ? 1 : 0); if (drq->wValue == FEATURE_ENDPOINT_HALT) { d12_status_set(p, epx, on); if ((epx == EPX_BULK_I) && !on && (p->fsm_bulk == FSM_BULK_STALL_TO_CSW)) { d12_buf_write(p, EPX_BULK_I, &p->csw, sizeof(struct csw)); p->fsm_bulk = FSM_BULK_IDLE; }#ifdef DBG printk("%s: %s_feature endpoint_halt on epx #%d\n", ID, on ? "set" : "clear", epx);#endif } else goto err; break; default: goto err; } ep_ctrl_ack(p); return 0;err:#ifdef DBG printk("%s: bad %s_feature request\n", ID, on ? "set" : "clear");#endif return 1;}static int std_clear_feature(struct d12 *p){ return feature(p, 0);}static int std_set_feature(struct d12 *p){ return feature(p, 1);}static int std_set_address(struct d12 *p){ struct devreq *drq; drq = &p->drq; if (drq->bmRequestType != (REQTYPE_DIR_OUT | REQTYPE_TYPE_STANDARD | REQTYPE_RECP_DEVICE)) goto err; if ((drq->wValue > 127) || drq->wIndex || drq->wLength) goto err; switch (p->fsm_dev) { case FSM_DEV_DEFAULT: if (drq->wValue) p->fsm_dev = FSM_DEV_ADDRESS; break; case FSM_DEV_ADDRESS: if (!drq->wValue) p->fsm_dev = FSM_DEV_DEFAULT; break; case FSM_DEV_CONFIGURED: goto err; } d12_set_address_enable(p, drq->wValue, 1);#ifdef DBG printk("%s: set_address %d\n", ID, drq->wValue);#endif ep_ctrl_ack(p); return 0;err:#ifdef DBG printk("%s: bad set_address request\n", ID);#endif return 1;}static int std_get_descriptor(struct d12 *p){ struct devreq *drq; int type, ndx; const void *buf; int len; drq = &p->drq; if (drq->bmRequestType != (REQTYPE_DIR_IN | REQTYPE_TYPE_STANDARD | REQTYPE_RECP_DEVICE)) goto err; type = (drq->wValue >> 8) & 0xFF; ndx = drq->wValue & 0xFF; switch (type) { case DESC_TYPE_DEVICE: if (ndx || drq->wIndex) goto err; buf = p->desc_dev; len = p->desc_dev_len;#ifdef DBG printk("%s: get_descriptor device\n", ID);#endif break; case DESC_TYPE_CONFIGURATION: if (ndx || drq->wIndex) /* only one configuration */ goto err; buf = p->desc_cfg; len = p->desc_cfg_len;#ifdef DBG printk("%s: get_descriptor configuration %d\n", ID, ndx);#endif break; case DESC_TYPE_STRING: if (!ndx) { if (drq->wIndex) goto err; } else { if ((ndx >= p->desc_str_max) || (drq->wIndex != DEF_LANG)) goto err; } buf = p->desc_str[ndx]; len = p->desc_str_len[ndx];#ifdef DBG printk("%s: get_descriptor string %d\n", ID, ndx);#endif break; default: goto err; } ep_ctrl_write(p, buf, len); return 0;err:#ifdef DBG printk("%s: bad get_descriptor request\n", ID);#endif return 1;}static int std_set_descriptor(struct d12 *p){#ifdef DBG printk("%s: unsupported set_descriptor request\n", ID);#endif return 1;}static int std_get_configuration(struct d12 *p){ struct devreq *drq; unsigned char buf[1]; drq = &p->drq; if (drq->bmRequestType != (REQTYPE_DIR_IN | REQTYPE_TYPE_STANDARD | REQTYPE_RECP_DEVICE)) goto err; if (drq->wValue || drq->wIndex || (drq->wLength != 1)) goto err; switch (p->fsm_dev) { case FSM_DEV_DEFAULT: goto err; case FSM_DEV_ADDRESS: buf[0] = 0; break; case FSM_DEV_CONFIGURED: buf[0] = CONFIG_VAL; break; } ep_ctrl_write(p, buf, drq->wLength);#ifdef DBG printk("%s: get_configuration --> %d\n", ID, buf[0]);#endif return 0;err:#ifdef DBG printk("%s: bad get_configuration request\n", ID);#endif return 1;}static int std_set_configuration(struct d12 *p){ struct devreq *drq; int cfg; drq = &p->drq; if (drq->bmRequestType != (REQTYPE_DIR_OUT | REQTYPE_TYPE_STANDARD | REQTYPE_RECP_DEVICE)) goto err; if ((drq->wValue & 0xFF00) || drq->wIndex || drq->wLength) goto err; cfg = drq->wValue & 0xFF; switch (p->fsm_dev) { case FSM_DEV_DEFAULT: goto err; case FSM_DEV_ADDRESS: if (cfg == CONFIG_VAL) { p->fsm_dev = FSM_DEV_CONFIGURED; p->fsm_bulk = FSM_BULK_IDLE; d12_set_endpoint_enable(p, 1); d12_stall_bulk(p, 0); } else if (cfg) goto err; break; case FSM_DEV_CONFIGURED: if (!cfg) { p->fsm_dev = FSM_DEV_ADDRESS; p->fsm_bulk = FSM_BULK_IDLE; d12_stall_bulk(p, 1); d12_set_endpoint_enable(p, 0); } else if (cfg != CONFIG_VAL) goto err; break; } ep_ctrl_ack(p);#ifdef DBG printk("%s: set_configuration %d\n", ID, cfg);#endif return 0;err:#ifdef DBG printk("%s: bad set_configuration request\n", ID);#endif return 1;}static int std_get_interface(struct d12 *p){ struct devreq *drq; unsigned char buf[1]; drq = &p->drq; if (drq->bmRequestType != (REQTYPE_DIR_IN | REQTYPE_TYPE_STANDARD | REQTYPE_RECP_INTERFACE)) goto err; if (drq->wValue || (drq->wLength != 1)) goto err; switch (p->fsm_dev) { case FSM_DEV_DEFAULT: case FSM_DEV_ADDRESS: goto err; case FSM_DEV_CONFIGURED: if (!(drq->wIndex & 0xFF)) /* only one interface / alternative setting */ buf[0] = 0; else goto err; break; } ep_ctrl_write(p, buf, drq->wLength);#ifdef DBG printk("%s: get_interface --> %d\n", ID, buf[0]);#endif return 0;err:#ifdef DBG printk("%s: bad get_interface request\n", ID);#endif return 1;}static int std_set_interface(struct d12 *p){ struct devreq *drq; drq = &p->drq; if (drq->bmRequestType != (REQTYPE_DIR_OUT | REQTYPE_TYPE_STANDARD | REQTYPE_RECP_INTERFACE)) goto err; if (drq->wLength) goto err; switch (p->fsm_dev) { case FSM_DEV_DEFAULT: case FSM_DEV_ADDRESS: goto err; case FSM_DEV_CONFIGURED: if ((drq->wIndex & 0xFF) || drq->wValue) /* only one interface / alternative setting */ goto err; d12_stall_bulk(p, 0); break; } ep_ctrl_ack(p);#ifdef DBG printk("%s: set_interface %d\n", ID, drq->wIndex & 0xFF);#endif return 0;err:#ifdef DBG printk("%s: bad set_interface request\n", ID);#endif return 1;}static int std_synch_frame(struct d12 *p){#ifdef DBG printk("%s: unsupported synch_frame request\n", ID);#endif return 1;}/* --- */static int cls_mass_storage_reset(struct d12 *p){ struct devreq *drq; drq = &p->drq; if (drq->bmRequestType != (REQTYPE_DIR_OUT | REQTYPE_TYPE_CLASS | REQTYPE_RECP_INTERFACE)) goto err; if (drq->wValue || drq->wLength) goto err; if (drq->wIndex) /* only one interface */ goto err; p->fsm_bulk = FSM_BULK_IDLE; ep_ctrl_ack(p);#ifdef DBG printk("%s: set_interface %d\n", ID, drq->wIndex & 0xFF);#endif return 0;err:#ifdef DBG printk("%s: bad (class) mass_storage_reset request\n", ID);#endif return 1;}static int cls_get_max_lun(struct d12 *p){ struct devreq *drq; unsigned char buf[1]; drq = &p->drq; if (drq->bmRequestType != (REQTYPE_DIR_IN | REQTYPE_TYPE_CLASS | REQTYPE_RECP_INTERFACE)) goto err; if (drq->wValue || (drq->wLength != 1)) goto err; if (drq->wIndex) /* only one interface */ goto err; buf[0] = p->max_lun - 1; ep_ctrl_write(p, buf, drq->wLength);#ifdef DBG printk("%s: (class) get_max_lun --> %d\n", ID, buf[0]);#endif return 0;err:#ifdef DBG printk("%s: bad (class) get_max_lun request\n", ID);#endif return 1;}/* --- */#define MAX_REQ_STANDARD 13static int (* const T_STD_SETUP[MAX_REQ_STANDARD])(struct d12 *) = { std_get_status, std_clear_feature, std_reserved, std_set_feature, std_reserved, std_set_address, std_get_descriptor, std_set_descriptor, std_get_configuration, std_set_configuration, std_get_interface, std_set_interface, std_synch_frame};#define MAX_REQ_CLASS 2static int (* const T_CLS_SETUP[MAX_REQ_CLASS])(struct d12 *) = { cls_mass_storage_reset, cls_get_max_lun};/* ------------------------------------------------------------------------- *//* * bulk and quazi-SCSI */#define BULK_NONE 0#define BULK_OUT 0#define BULK_IN 1#define SCHD_ERR_PHASE 1#define SCHD_ERR_INVALID_CDB 2#define SCHD_ERR_INVALID_LBA 3static void ep_bulk_write(struct d12 *p, const void *buf, int len){ if (p->bxferptr + len > p->bxferlen) len = p->bxferlen - p->bxferptr; if (len > MAX_CHUNKBUF) len = MAX_CHUNKBUF; p->bbuf = (unsigned char *)buf; p->blen = len; p->bptr = 0; len = d12_buf_write(p, EPX_BULK_I, p->bbuf, len); p->bptr += len; p->bxferptr += len; p->fsm_bulk = FSM_BULK_DATA_IN;}static void ep_bulk_read(struct d12 *p, void *buf, int len){ if (p->bxferptr + len > p->bxferlen) len = p->bxferlen - p->bxferptr; if (len > MAX_CHUNKBUF) len = MAX_CHUNKBUF; p->bbuf = (unsigned char *)buf; p->blen = len; p->bptr = 0; if (p->fsm_bulk == FSM_BULK_DATA_OUT_WAIT) { len = d12_buf_read(p, EPX_BULK_O, p->bbuf, len); p->bptr += len; p->bxferptr += len; } p->fsm_bulk = FSM_BULK_DATA_OUT;}/* --- */static int bulk_xfer_chk(struct d12 *p, int dir, int len){ struct cbw *cbw; struct csw *csw; int h, hi; cbw = &p->cbw; csw = &p->csw; h = cbw->dCBWDataTransferLength; hi = cbw->bmCBWFlags & CBW_FLAGS_DIR_IN; p->bxferlen = p->bxferptr = 0; if (dir == BULK_IN) { /* Di */ if (!h) /* Hn < Di */ goto phaserr; else if (hi) { /* Hi ? Di */ if (h >= len) /* Hi >= Di */ p->bxferlen = len; else /* Hi < Di */ goto phaserr; } else /* Ho <> Di */ goto phaserr; } else if (len) { /* Do */ if (!h) /* Hn < Do */ goto phaserr; else if (hi) /* Hi <> Do */ goto phaserr; else { /* Ho ? Do */ if (h >= len) /* Ho >= Do */ p->bxferlen = len; else /* Ho < Do */ goto phaserr; } } return 0;phaserr: csw->bCSWStatus = CSW_STAT_PHASE_ERROR; csw->dCSWDataResidue = h; return SCHD_ERR_PHASE;}static int bulk_xfer(struct d12 *p, int dir, const void *buf, int len){ int r; r = bulk_xfer_chk(p, dir, len); if (!r && len) { if (dir == BULK_IN) ep_bulk_write(p, buf, len); else ep_bulk_read(p, (void *)buf, len); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -