/* * Context: tasklet */ static int oz_usb_vendor_class_req(void *hpd, u8 req_id, u8 req_type, u8 request, __le16 value, __le16 index, const u8 *data, int data_len) { struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; struct oz_pd *pd = usb_ctx->pd; struct oz_elt *elt; struct oz_elt_buf *eb = &pd->elt_buff; struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); struct oz_vendor_class_req *body; if (ei == NULL) return -1; elt = (struct oz_elt *)ei->data; elt->length = sizeof(struct oz_vendor_class_req) - 1 + data_len; body = (struct oz_vendor_class_req *)(elt+1); body->type = OZ_VENDOR_CLASS_REQ; body->req_id = req_id; body->req_type = req_type; body->request = request; put_unaligned(value, &body->value); put_unaligned(index, &body->index); if (data_len) memcpy(body->data, data, data_len); return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); }
/* * Context: softirq */ int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type, u8 index, u16 windex, int offset, int len) { struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; struct oz_pd *pd = usb_ctx->pd; struct oz_elt *elt; struct oz_get_desc_req *body; struct oz_elt_buf *eb = &pd->elt_buff; struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); oz_dbg(ON, " req_type = 0x%x\n", req_type); oz_dbg(ON, " desc_type = 0x%x\n", desc_type); oz_dbg(ON, " index = 0x%x\n", index); oz_dbg(ON, " windex = 0x%x\n", windex); oz_dbg(ON, " offset = 0x%x\n", offset); oz_dbg(ON, " len = 0x%x\n", len); if (len > 200) len = 200; if (ei == NULL) return -1; elt = (struct oz_elt *)ei->data; elt->length = sizeof(struct oz_get_desc_req); body = (struct oz_get_desc_req *)(elt+1); body->type = OZ_GET_DESC_REQ; body->req_id = req_id; put_unaligned(cpu_to_le16(offset), &body->offset); put_unaligned(cpu_to_le16(len), &body->size); body->req_type = req_type; body->desc_type = desc_type; body->w_index = windex; body->index = index; return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); }
/*------------------------------------------------------------------------------ * Context: softirq */ int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type, u8 index, u16 windex, int offset, int len) { struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; struct oz_pd *pd = usb_ctx->pd; struct oz_elt *elt; struct oz_get_desc_req *body; struct oz_elt_buf *eb = &pd->elt_buff; struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); if (len > 200) len = 200; if (ei == 0) return -1; ei->callback = oz_usb_setup_elt_completion_callback; ei->context = req_id; elt = (struct oz_elt *)ei->data; elt->length = sizeof(struct oz_get_desc_req); body = (struct oz_get_desc_req *)(elt+1); body->type = OZ_GET_DESC_REQ; body->req_id = req_id; put_unaligned(cpu_to_le16(offset), &body->offset); put_unaligned(cpu_to_le16(len), &body->size); body->req_type = req_type; body->desc_type = desc_type; body->w_index = windex; body->index = index; return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); }
/*------------------------------------------------------------------------------ * Context: process */ ssize_t oz_cdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *fpos) { struct oz_pd *pd; struct oz_elt_buf *eb; struct oz_elt_info *ei = 0; struct oz_elt *elt; struct oz_app_hdr *app_hdr; struct oz_serial_ctx *ctx; if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr)) return -EINVAL; spin_lock_bh(&g_cdev.lock); pd = g_cdev.active_pd; if (pd) oz_pd_get(pd); spin_unlock_bh(&g_cdev.lock); if (pd == 0) return -1; eb = &pd->elt_buff; ei = oz_elt_info_alloc(eb); if (ei == 0) { count = 0; goto out; } elt = (struct oz_elt *)ei->data; app_hdr = (struct oz_app_hdr *)(elt+1); elt->length = sizeof(struct oz_app_hdr) + count; elt->type = OZ_ELT_APP_DATA; ei->app_id = OZ_APPID_SERIAL; ei->length = elt->length + sizeof(struct oz_elt); app_hdr->app_id = OZ_APPID_SERIAL; if (copy_from_user(app_hdr+1, buf, count)) goto out; spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]); ctx = (struct oz_serial_ctx *)pd->app_ctx[OZ_APPID_SERIAL-1]; if (ctx) { app_hdr->elt_seq_num = ctx->tx_seq_num++; if (ctx->tx_seq_num == 0) ctx->tx_seq_num = 1; spin_lock(&eb->lock); if (oz_queue_elt_info(eb, 0, 0, ei) == 0) ei = 0; spin_unlock(&eb->lock); } spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]); out: if (ei) { count = 0; spin_lock_bh(&eb->lock); oz_elt_info_free(eb, ei); spin_unlock_bh(&eb->lock); } oz_pd_put(pd); return count; }
/*------------------------------------------------------------------------------ * Context: tasklet */ static int oz_usb_set_config_req(void *hpd, u8 req_id, u8 index) { struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; struct oz_pd *pd = usb_ctx->pd; struct oz_elt *elt; struct oz_elt_buf *eb = &pd->elt_buff; struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); struct oz_set_config_req *body; if (ei == 0) return -1; elt = (struct oz_elt *)ei->data; elt->length = sizeof(struct oz_set_config_req); body = (struct oz_set_config_req *)(elt+1); body->type = OZ_SET_CONFIG_REQ; body->req_id = req_id; body->index = index; return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); }
/* * Context: tasklet */ static int oz_usb_set_interface_req(void *hpd, u8 req_id, u8 index, u8 alt) { struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; struct oz_pd *pd = usb_ctx->pd; struct oz_elt *elt; struct oz_elt_buf *eb = &pd->elt_buff; struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); struct oz_set_interface_req *body; if (ei == NULL) return -1; elt = (struct oz_elt *)ei->data; elt->length = sizeof(struct oz_set_interface_req); body = (struct oz_set_interface_req *)(elt+1); body->type = OZ_SET_INTERFACE_REQ; body->req_id = req_id; body->index = index; body->alternative = alt; return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); }
/*------------------------------------------------------------------------------ * Context: tasklet */ static int oz_usb_set_clear_feature_req(void *hpd, u8 req_id, u8 type, u8 recipient, u8 index, __le16 feature) { struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; struct oz_pd *pd = usb_ctx->pd; struct oz_elt *elt; struct oz_elt_buf *eb = &pd->elt_buff; struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); struct oz_feature_req *body; if (ei == 0) return -1; elt = (struct oz_elt *)ei->data; elt->length = sizeof(struct oz_feature_req); body = (struct oz_feature_req *)(elt+1); body->type = type; body->req_id = req_id; body->recipient = recipient; body->index = index; put_unaligned(feature, &body->feature); return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); }